NET框架程序设计(上).ppt_第1页
NET框架程序设计(上).ppt_第2页
NET框架程序设计(上).ppt_第3页
NET框架程序设计(上).ppt_第4页
NET框架程序设计(上).ppt_第5页
已阅读5页,还剩138页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

.NET框架程序设计(上),2,第一章 .NET 简介,1.1 .NET 简介 1.2 .NET Framework 的结构 1.3 Visual Studio 2005 1.4 小结,1.1 .NET 简介,1.1.1 .NET战略构想 1.1.2 .NET战略要点 1.1.3 什么是.NET 1.1.4 .NET特点,.NET战略构想,1. 未来5年,我们的目标就是超越现在各自为营的Web站点,把Internet建成一个可以交换组件的地方比尔盖茨。 2.比尔盖茨表示:“互联网至今的影响非常壮观,然而技术创新的步伐在随后的5年中会更快。我们的目标是把今天孤立静止的各个网站变成彼此间可交流的互联网家族成员,那时设备和服务将集成成为连贯一致,并由用户主导的计算体验。” 3.微软总裁兼首席执行官巴尔默说:“互联网革命现在必须进入下一阶段:使现有的大量信息和资源能相互协作。通过创建一个统一的平台,使各种设备和服务互相协作,微软将为开发商提供新一轮发展和创新契机,从而使我们进入功能更强、操作更简化的计算时代。”,.NET战略要点,1.改革商务模型 2.提高软件开发生产效率,并且试图使应用软件的发布更为容易。 3.微软.NET战略中的重要棋子C#: 4.未来的软件,什么是.NET,2000年微软的白皮书这样定义.NET:Microsoft.NET 是Microsoft XML Web Services 平台。XML Web Services 允许应用程序通过 Internet 进行通讯和共享数据,而不管所采用的是哪种操作系统、设备或编程语言。 简而言之,.NET是一种面向网络、支持各种用户终端的开发平台环境。 .NET的核心就是要搭建第三代因特网平台,这个网络平台将解决网站之间的协同合作问题,从而最大限度的获取信息。更具体地说,Microsoft 正在五个方面创建 .NET 平台,即工具、服务器、XML Web 服务、客户端和 .NET 体验。,.NET特点,1.面向对象的编程,尤其是C#,是完全的面向对象编程。 2.语言的独立性,各种语言都可以编译为中间语言。 3.对动态Web页面的支持,使得源代码和页面文件分离,并在服务器端编译运行。 4.装配件的自我描述结构杜绝了因版本冲突问题或其他应用程序覆盖共享装配件而产生的错误,节约了成本和时间。 5.增强的安全性,每个装配件都可以包含内置的安全信息,这些信息可以准确地指出谁或哪种类型的用户或进程可以调用什么类的哪些方法。 6. Web服务的支持。业界的许多人士认为Web服务是未来几年里的重头戏,.NET集成了对开发Web服务的完全支持,用户可以开发出任何类型的应用程序。 7.完善的内存和资源管理的便捷性。,1.2 .NET Framework 的结构,1.2.1 .NET Framework概述 1.2.2 .NET Framework架构 1.2.3 公共语言运行时(CLR) 1.2.4 公共语言运行库 1.2.5 通用类型系统,.NET Framework概述,.NET Framework 是支持生成和运行下一代应用程序和 XML Web services 的内部 Windows 组件。 .NET Framework 旨在实现下列目标: 1.提供一个一致的面向对象的编程环境,而无论对象代码是在本地存储和执行,还是在本地执行但在 Internet 上分布,或者是在远程执行的。 2.提供一个将软件部署和版本控制冲突最小化的代码执行环境。,.NET Framework概述(续),3.提供一个可提高代码(包括由未知的或不完全受信任的第三方创建的代码)执行安全性的代码执行环境。 4.提供一个可消除脚本环境或解释环境的性能问题的代码执行环境。 5.使开发人员的经验在面对类型大不相同的应用程序(如基于 Windows 的应用程序和基于 Web 的应用程序)时保持一致。 6.按照工业标准生成所有通信,以确保基于 .NET Framework 的代码可与任何其他代码集成。,.NET Framework架构,.NET Framework 体系结构图 :,.NET Framework架构,1. .NET Framework 它为创建和运行.NET 应用程序提供了必要的编译和运行基础。 它的主要组件是公共语言运行时(CLR,Common Language Runtime)和.NET Framework类库(FCL, Framework Class Library)。 CLR抽象操作系统服务并作为执行引擎为托管应用程序服务,托管应用程序的每一个操作都受CLR控制。FCL提供面向对象的API。该API供托管应用程序写入。,.NET Framework架构,2. 平台基础和应用程序服务 .NET Framework 可以运行于Windows操作系统上,也可以运行在Windows操作系统上的各种应用程序服务,如COM等。 3.公共语言运行时(CLR) 公共语言运行时简化了应用程序的开发,提供了一个强大的、安全的执行环境,支持多语言,并简化了应用程序的部署和管理。 公共语言运行时也称为“托管环境”,在这个托管环境中将自动提供诸如垃圾回收和安全性等通用服务 。 4.基类库 基类库体现了运行库的特性,并且为开发人员提供了所需的其他高级服务,简化了.NET 应用程序的开发,开发人员可通过创建自己的类库扩展它们。,.NET Framework架构,5. ADO.NET 和XML ADO.NET为非连接编程模型提供了改进的支持,同时也提供了丰富的XML支持。 6.ASP.NET 和Windows窗体 ASP.NET 和Windows窗体分别是建立在公共语言运行库上的编程框架,可以使用ASP.NET和Windows窗体在服务器上构建功能强大的Web和Windows应用程序。 7.语言 任何符合公共语言规范(CLS,Common Language Specification)的语言都能运行在公共语言运行库上。 在.NET Framework 中,Microsoft支持VB ,C,C和Microsoft Jscript等多种编程语言,还支持第三方提供的其他语言。,公共语言运行时(CLR),CLR(Common Language Runtime 公共语言运行时)是整个.NET平台的基础,也是平台的核心。 CLR的核心是一个执行引擎,它加载、执行和管理已经编译的“中间字节代码格式”的代码,这种代码名字叫做MSIL或者IL(Microsoft Intermediate Languag 微软中间语言 )。这种代码不被解释,在执行前通过内置在CLR中的即时编译器把它编译成本地的二进制代码。 .NET有两个级别的编译器,语言编译器把源代码编译成IL,执行时再被编译成二进制代码。这种技术,使交叉语言继承成为可能。,公共语言运行库,公共语言运行库,.NET 类库支持:通过和运行时集成代码来支持.NET Framework类库 COM封送拆收器:提供和 COM 组件之间的封送 线程:提供多线程编程支持 异常管理器:提供和 Windows 结构化异常处理集成的异常处理机制 类型检查器:不允许不安全的类型转换和未初始化变量 MSIL 可被校验以保证类型安全 调试器:使开发者能够调试应用程序和根据代码执行 安全引擎:提供基于证据的安全, 基于用户身份和代码来源 垃圾回收器:为.NET Framework下的所有对象提供自动生命期管理,支持多处理器,可扩展 代码管理器:管理和执行代码 Microsoft中间语言到本地代码编译器:通过即时编译把 Microsoft 中间语言转换成本地代码 类加载器:管理元数据,加载和在内存中布局类,通用类型系统,通用类型系统定义了如何在运行库中声明、使用和管理类型,同时也是运行库支持跨语言集成的一个重要组成部分 通用类型系统执行以下功能: 1建立一个支持跨语言集成、类型安全和高性能代码执行的框架。 2提供一个支持完整实现多种编程语言的面向对象的模型。 3定义各语言必须遵守的规则,有助于确保用不同语言编写的对象能够交互作用。,1.3Visual Studio 2005,1.3.1 统观全局 1.3.2 Visual Studio的扩展 1.3.3 开发工具路线图 1.3.4 Visual Studio 2005新特性 1.3.5 案例,统观全局,统观全局,Visual Studio 是一套完整的开发工具集,用于生成 ASP.NET Web 应用程序、XML Web Services、桌面应用程序和移动应用程序。Visual Basic、Visual C+、Visual C# 和 Visual J# 全都使用相同的集成开发环境 (IDE),利用此 IDE 可以共享工具且有助于创建混合语言解决方案。另外,这些语言利用了 .NET Framework 的功能,通过此框架可使用简化 ASP Web 应用程序和 XML Web Services 开发的关键技术。,Visual Studio的扩展,Visual Studio的扩展,Visual Studio 2005中增加了一个非常重要的功能团队开发。 Visual Studio 2005 Team System 是一个高效、集成且可扩展的软件开发生命周期工具平台,可以帮助软件团队提高整个软件开发过程中的通信和协作能力。 团队中的各个角色可以对项目生命周期中的各个阶段进行管理。,开发工具路线图,开发工具路线图,Visual Studio 2005是在Visual Studio 2003的基础上开发出来了,所以它兼容了Visual Studio 2003中的所有功能,同时也有了一些改进,并把 SQL Server 2005的Express版本和 Visual Studio 2005 Team System都集成进来,使Visual Studio的功能更加强大,整个体系也更加完整。,Visual Studio 2005新特性,重构(Refactioring)支持:可以抽取代码并将其包围在自己的方法内。 编辑并继续:开发人员可以在调试状态下一边运行应用程序一边修改代码,然后从修改的断点继续执行。 代码段:提供了为常见情况预编写的代码段。,案例,案例 1:创建Web应用程序 “文件”“新建”“网站”“ASP.NET网站”,在其页面加载方法中在页面上输出“hello world”字符串。,protected void Page_Load(object sender, EventArgs e) Response.Write(“hello world“); ,案例,案例2:创建Windows应用程序 “文件”“新建”“项目”“Windows应用程序”,在点击按钮事件中弹出消息框 。,private void button1_Click(object sender, EventArgs e) MessageBox.Show(“hello world“); ,案例,案例3:创建控制台应用程序 “文件”“新建”“项目”“控制台应用程序”,输出“hello world”。,static void Main(string args) Console.WriteLine(“hello world“); /为了使命令框能停住,加个输入语句 Console.ReadLine(); ,1.4小结,通过本章的学习,我们了解了什么是.NET Framework。.NET Framework是由公共语言运行时和类库构成的。有多种类型的.NET Framework应用程序,它们被广泛应用到各种领域中。.NET Framework已成为未来大多数应用程序的基础。,31,第二章公共语言运行库,2.1开发托管代码:通用类型系统(CTS) 2.2 通用类型系统架构 2.3 特殊系统类型 2.4 小结,2.1 开发托管代码:通用类型系统CTS,编程语言是什么?有一种看法是把它当成拥有一套关键字的特定语法,这些关键字可用于定义数据,并表达实施于数据上的操作。尽管编程语言的语法各有差别,但大多数流行语言的潜在抽象性其实十分相似,它们都支持形形色色的数据类型(如整型和字符型),都可将代码包装于方法(函数)之中,并且都提供一个将数据和方法聚合于类的办法。定义一个崭新的编程语言时,常规做法是先定义诸如关键语义的抽象性,然后才是语法。,2.1 开发托管代码:通用类型系统CTS,与此同时,亦存在另一种可能性。假设为一个编程模型定义核心抽象性质,而且不把它映射到任何特定语法上,如果抽象性够一般化,它就可以被用于多种不同的编程语言中。让语法和语义保持隔离,允许不同的语言使用同一套潜在抽象性,这正是CLR的通用类型系统(Common Type System,CTS)的功能。 CTS并未规定特定语法或关键字,只是定义了一套通用类型,它们可用于许多语言的语法上。每一种语言都可以自由定义它所希望的任何语法,但如果某个语言基于CLR,它将至少使用CTS定义的一部分类型。,2.1 开发托管代码:通用类型系统CTS,对任何一门编程语言来说,类型都是基础性的东西。想像某种类型的一个形象的方法是,把它当做一套“用来解释存储在某内存位置上的值(如变量的值)”的规则。例如,如果变量的类型是整数,变量的值就被解释为一个整数;如果变量的类型是字符串,变量的值就被解释为一组字符。当然,对编译器来说,类型的含义远不止于此,编译器还必须能够理解以下规则:“定义每一种类型能够接受的值”,以及“对这些值来说哪些操作合法”。利用这些知识以及其他信息,编译器便能够决定一个特定类型的值是否被正确使用。,2.1 开发托管代码:通用类型系统CTS,CTS定义的一整套类型在CLR中居核心位置。基于CLR的编程语言以一种语言相依方式来使用这些类型。尽管一个基于CLR的编程语言的创造者可以自由实现CTS定义类型的任何子集,甚至加入自己的类型,但大多数基于CLR的语言还是广泛地采用了CTS所定义的类型。,2.2 通用类型系统架构,2.2.1 值类型和引用类型 2.2.2 值类型和引用类型之间的相互转换: 装箱和拆箱,2.2通用类型系统架构,图2.1显示了CTS定义的大部分类型的子集。值得注意的是: 每种类型都直接或间接继承名为Object的类型CTS定义的每一个类型不是引用类型就是值类型。顾名思义,引用类型的实例总是包含对该类型的值的引用,而值类型的实例包含值本身。引用类型直接继承Object(如String类),值类型直接继承名为ValueType的类型(如Int32型),而ValueType类型同样继承自Object。,2.2通用类型系统架构,值类型和引用类型,值类型继承自ValueType,值类型的变量直接存储数据,被分配在堆栈中,并且永远不可能为空。这一类的变量类型包括字节型、字符型、各种长度的有符号和无符号整型、单精度和双精度浮点型、十进制类型、布尔类型等。,值类型和引用类型,引用类型继承自Object,引用类型实例存储的是数据在内存中的地址,被分配在可以进行垃圾回收的堆中。由于一份数据可以被多个变量引用,使用这种变量类型能够起到节省内存资源的作用;但是一个引用对数据进行的修改也会影响到其他的引用,因为它们都指向同一个数据源。引用类型的变量可以为空,表示它不指向任何对象。与值类型相比,引用类型通常更为复杂,例如,类、接口、数组和字符串都是引用类型,如图2.1所示。,值类型和引用类型,接下来介绍值类型和引用类型之间的区别。CTS中,必须了解的基本特点是内存如何分配给每种类型的实例。在托管代码中,值可通过两种主要方式中的任一种分配其内存,两种方式都是由CLR管理:在堆栈(Stack)中分配或在堆(Heap)中分配。,值类型和引用类型,分配在托管堆栈中的变量通常是在调用方法时或者正在运行的方法创建这些变量时创建,无论哪种情况,堆栈变量所使用的内存将在创建它们的方法返回时自动获得释放。但是,分配在托管堆上的变量不会在创建它们的方法结束时释放其内存。相反,这些变量所使用的内存通过称为垃圾回收的过程进行释放。,值类型和引用类型,例如,在一个方法中声明了4个内存变量,3个值类型Int16、Char和Int32(临时变量A)的数据在托管堆栈上创建,而引用类型String(变量B)的一个实例存在于托管堆上,如图2.2所示。A的值是169,在该方法调用返回时,A在堆栈上所占用的内存将会自动释放。B指向的值是Hello,在该方法调用返回时,B在堆栈上所占用的内存将会自动释放,但是在堆上的值会在垃圾回收时才释放。,值类型和引用类型,图2.2值类型和应用类型,值类型和引用类型,【例2.1】值类型的传递示例 protected void Page_Load(object sender, System.EventArgs e) int a,b; a=5; b=a; b+=5; add5(b); Response.Write(“a=“+a); Response.Write(“); Response.Write(“b=“+b); public void add5(int num) num+=5; ,值类型和引用类型,程序运行结果如图2.3所示。因为int是值类型,所以加5后的结果不能带到方法外,因此输出变量b的值仍为10。 图2.3值类型传递结果,值类型和引用类型,引用类型传递形式1:使用方法参数ref,使方法引用传递到方法的同一个变量。当控制结果传递回调用方法时,在方法中对参数所作的任何更改都将反映在该变量中。 在 .NET 中,可以实现传递引用的还有out,ref与out的区别在于,参数在传到ref之前必须先被初始化,但传到out之前不必显式初始化。,值类型和引用类型,【例2.2】引用类型传递示例。 protected void Page_Load(object sender, System.EventArgs e) int a,b; a=5; b=a; b+=5; add5(ref b); Response.Write(“a=“+a); Response.Write(“); Response.Write(“b=“+b); public void add5(ref int num) num+=5; ,值类型和引用类型,程序运行结果如图2.4所示。使用ref传递的是引用,所以在方法中所作的更改可以反映在变量中,因此输出变量b的值为15。 图2.4ref引用类型传递结果,值类型和引用类型,【例2.3】引用类型传递示例。 using System.Text protected void Page_Load(object sender, System.EventArgs e) / 在此处放置用户代码以初始化页面 StringBuilder name1=new StringBuilder(“hello“); StringBuilder name2; name2=name1; name2.Append(“!“);/在字符串的末尾填加另一个字符串 Response.Write(name1); Response.Write(“); Response.Write(name2); Response.Write(“); test(name2); Response.Write(name2+“); Response.Write(name1); public void test(StringBuilder name) name.Append(“); ,值类型和引用类型,执行结果如图2.5所示。 图2.5引用类型传递,值类型和引用类型,值类型和引用类型之间的基本区别是: 值类型的单独实例分配在堆栈上,通过复制赋值,默认通过值来传递参数,除非用ref关键字。 引用类型的实例只在堆栈上分配了对其实际值的引用,值本身分配在堆上,通过引用赋值,可能出现几个引用指向同一个对象,因此对一个变量的操作会影响另一个变量所引用的同一对象,用引用来传递变量。,2.2.2 值类型和引用类型之间的相互转换: 装箱和拆箱,有时候需要将一个值类型实例当成一个引用类型实例来看待。例如,要将一个值类型实例作为参数,传递给某个方法,但该参数被定义为一个指向值类型实例的引用,而不是一个值。可以通过一个装箱过程,将值类型实例转换成一个引用类型实例。,2.2.2 值类型和引用类型之间的相互转换: 装箱和拆箱,当一个值类型实例被装箱时,对应存储区分配于堆上,该实例的值也被复制到为该值分配的存储空间中,而对此存储区的一个引用则被置于堆栈上;被装箱的值是个对象,亦即一个引用类型,它包含了值类型实例的内容。如图2.3所示,类型Int32的实值已被转换为一个类型Object的值,其内容169已被置于堆上。经过装箱的值类型实例也可被转换回其原始形式,此过程称为拆箱。装箱和拆箱能有助于统一地考察类型系统,其中任何类型的值最终都可以按对象处理。,2.2.2 值类型和引用类型之间的相互转换: 装箱和拆箱,图2.3装箱和拆箱,2.2.2 值类型和引用类型之间的相互转换: 装箱和拆箱,【例2.4】一个简单的装箱和拆箱的例子。 public static void Main() int i = 10; object obj = i;/将i装箱 Console.WriteLine(i + “,“ + (int)obj); /Console.WriteLine方法用的参数是String对象,因此, i+“,“+(int)obj中,i需要进行 /一次装箱(转换成String对象), /(int)obj将obj对象拆箱成值类型,而根据WriteLine方法输出的应 为String类型,故又需要将/(int)obj值装箱成引用类型。 Console.ReadLine(); ,2.2.2 值类型和引用类型之间的相互转换: 装箱和拆箱,程序运行结果如图2.4所示。 图2.4装箱拆箱程序运行结果,2.2.2 值类型和引用类型之间的相互转换,【例2.5】多次装箱和拆箱示例 using System.Collections; static void Main(string args) int count; DateTime startTime = DateTime.Now; ArrayList myArrayList = new ArrayList(); /装箱和拆箱对性能的影响更偏重于大型的程序和软件 / 重复5次测试 for (int i = 5; i 0; i-) myArrayList.Clear(); / 将值类型加入myArrayList数组 for (count = 0; count 5000000; count+) myArrayList.Add(count); /装箱 / 重新得到值 int j; for (count = 0; count 5000000; count+) j = (int)myArrayListcount; /拆箱 / 打印结果 DateTime endTime = DateTime.Now; Console.WriteLine(“Start: 0nEnd: 1nSpend: 2“, startTime, endTime, endTime - startTime); Console.WriteLine(“Push ENTER to return commandline.“); Console.ReadLine(); /循环中包含一次装箱和一次拆箱(这里均忽略两个程序打印时的装箱操作), /当循环次数足够大的时候,性能差异是明显的。 ,2.2.2 值类型和引用类型之间的相互转换: 装箱和拆箱,该程序在双核CPU、主频1.67GHz、内存1.5GB的计算机上运行,其结果如图所示。,2.3特殊系统类型,2.3.1 泛型 2.3.2 Nullable类型,泛型,1. 泛型的定义 所谓泛型,即通过参数化类型来实现在同一份代码上操作多种数据类型。泛型类型是一种编程范式,它利用“参数化类型”将类抽象化,从而实现更为灵活的复用;即在定义时为一种抽象的数据类型,到具体使用的时候用什么类型实例化就是什么类型。 泛型赋予了代码更强的安全性、更好的复用、更高的效率、更清晰的约束。,泛型,2. 为什么要使用泛型 前文介绍了装箱和拆箱在数据量很大的时候,实际上系统性能非常低,为了解决这个问题,在VS2005中提出了泛型的概念。 如果没有泛型,通用数据结构可通过使用类型Object 实现任何数据类型的存储。 (1)编译时类型验证。C#泛型代码在被编译为MSIL和元数据时,采用特殊的占位符来表示泛型类型,并用专有的MSIL指令支持泛型操作。而真正的泛型实例化工作发生在JIT编译时。 (2)高性能(不用装箱,不用转换)。C#泛型能力由CLR在运行时支持,这使得泛型能力可以在各个支持CLR的语言之间进行无缝的互操作。,泛型,3. 泛型机制 泛型由CLR在运行时支持,区别于C+编译时的模板机制。泛型代码在被编译为MSIL代码和元数据时,采用特殊的占位符表示泛型类型,并用专用的MSIL指令支持泛型操作,而真正的泛型实例化是在JIT编译时。 第一轮编译时,编译器只为泛型类型产生“泛型版”的MSIL代码与元数据,并不进行泛型类型的实例化,泛型参数在中间只是占位符;第二轮JIT编译时,当JIT第一次遇到泛型参数时,将用实际参数类型替换泛型参数并进行实例化。 CLR为所有引用类型的参数创建同一份代码,但如果类型参数为值类型,对每一个不同的值类型产生独立的一份代码。,泛型,【例2.6】泛型类型的使用在编译时就可发现类型转换中的错误 static void Main(string args) /使用泛型,在编译时就能报错 /在定义List泛型类时没有指定集合成员的类型,成 员在实例化的时候才指定 List list = new List(); /加入String类型的对象,编译正常 list.Add(“str1“); /加入整型变量,编译出错 / list.Add(1); Console.WriteLine(list0); ,泛型,4. 泛型的特点 .NET Framework 2.0 在System.Collections.Generic 和System.Collections. ObjectModel命名空间中提供了多个泛型集合类,使用这些类可以取得以下所述的各种优势。 1)可重用性 定义一个泛型类型,在多种场合使用,而不需要对代码进行任何更改。例如,要编写代码来将两个数相加,在出现泛型这个概念之前,达到此目的的最好方法是用不同的数据类型对Sum()方法进行重载并返回值。然而,现在可以创建一个泛型方法来将这两个数相加,并用所需数据类型的值调用该方法。,泛型,2)类型安全 泛型数据类型提供更好的类型安全性,尤其是在使用集合的情况下。在Collection 类中,当添加对象时,编译器不会对正在添加的对象的类型进行检查,因此,运行时的强制转换可能失败。另外,可以通过使用泛型来定义在编译时传递给集合和编译器的对象类型,以确保仅传递这些对象,这将增强类型安全性,并降低发生类型强制转换错误的可能性。 3)性能 由于泛型类型降低了对变量或对象进行装箱、拆箱和类型强制转换的需要,因此它的性能优于普通系统类型。,泛型,5. 泛型约束 在定义泛型类时,可以对客户端代码能够在实例化类时用于类型参数的类型种类施加限制。如果客户端代码尝试使用某个不允许的类型来实例化类,则会产生编译时错误,这些限制称为约束,如表2.1所示。,泛型,表2.1 泛型约束,泛型,如果要检查泛型列表中的某个项以确定它是否有效,或者将它与其他某个项进行比较,则编译器必须在一定程度上保证它需要调用的运算符或方法将受到客户端代码可能指定的任何类型参数的支持。这种保证是通过对泛型类定义应用一个或多个约束获得的。例如,基类约束告诉编译器:仅此类型的对象或从此类型派生的对象才可用作类型参数。一旦编译器有了这个保证,它就能够允许在泛型类中调用该类型的方法。,泛型,约束使用上下文关键字 where 指定,例2.6的代码说明了如何在C# 中实现泛型。该代码体现了使用泛型时,在可重用性和类型安全方面取得的优势。该代码示例定义名为CustomList的泛型类,该类用于创建对象,但由于定义了约束条件,所以类型参数只能是值类型。,Nullable类型,作为开发人员,可能会发现经常需要使用值类型尚未定义的值。例如,一个银行系统需要一个值以区分数据库中的浮点型工资字段是否已被赋值,0显然不是一个适合的值,因为它无法表示该字段的值是0还是没有被赋值,这时就需要一个null值来完成这项工作。可是值类型并没有定义null值,如果为这个值类型变量赋关键字null,则编译器将抛出一个错误。.NET Framework 2.0 提供了一个名为Nullable的数据类型,可以用来为值类型变量赋null值。Nullable数据类型既可以存储null值又可以存储一组普通值,因此,可以使用Nullable类型来存储该工资字段,当该字段还未被赋值时,将它的值置为 null,赋值后存储实际的浮点型数据。,Nullable类型,所有的Nullable类型都使用泛型System.Nullable结构进行实例化,此结构结合了基础类型的值与二进制null指示器。这使Nullable类型在使用时与普通数据类型一样方便。,Nullable类型,例2.7的代码说明了如何使用C# 声明Nullable类型。该代码示例定义了一个由成员字段组成的Employee类,用于存储有关雇员姓名、婚姻状况和结婚周年纪念日等信息。该类将周年纪念日字段定义为Nullable,并确保该字段在雇员未婚的情况下存储一个null值。当从这些字段中检索值时,该类使用HasValue属性,该属性在Nullable类型中可用,且该属性有助于确定Nullable字段是已被赋值还是包含一个null值。,Nullable类型,【例2.7】Nullable类型示例 static void Main(string args) /初始化雇员类 Employee e1 = new Employee(“Stephen“, true); /为该雇员定义结婚周年 e1.Anniversary = DateTime.Today.AddMonths(-5); e1.ShowDetails(); Employee e2 = new Employee(“Thomas“, false); e2.Anniversary = DateTime.Today.AddMonths(-10); e2.ShowDetails(); Console.ReadLine(); /定义雇员类 class Employee /声明字段 private string _name; private bool _married; private Nullable _mAnniversary;,/在构造函数中初始化姓名和是否已婚以及结婚周年的时间 public Employee(string name, bool married) this._name = name; this._married = married; if (!this._married) this._mAnniversary = null; /定义周年属性 public Nullable Anniversary get return this._mAnniversary; set if (this._married) this._mAnniversary = value; else this._mAnniversary = null; ,Nullable类型,public void ShowDetails() Console.WriteLine(); Console.WriteLine(“Name:0“, this._name); Console.WriteLine(“Married:0“, this._married ? “YES“ : “NO“); if (this._mAnniversary.HasValue) Console.WriteLine(“Anniversary:0:MMMM d“, this._mAnniversary); else Console.WriteLine(“Anniversary:none“); ,Nullable类型,运行结果如图所示。,2.4小结,本章主要学习了公共语言运行库的相关知识。通用语言运行时的核心是通用类型系统。通用类型系统中的类型可分为两类:值类型和引用类型,它们可以通过装箱操作和拆箱操作相互转换。 .NET Framework 2.0引入了泛型,这是一种非常有用的类型,需要牢固掌握。,课后习题,1. 在托管环境下,下面哪些描述是正确的?请选择所有符合条件的答案。 A. 系统自动提供诸如垃圾回收、安全性等通用服务 B. 如果需要,开发人员都可以关闭代码安全验证功能 C. 如果需要,垃圾回收可以手动进行 D. 开发者不能跟踪代码的执行 E. 运行时,代码与类库是独立的,课后习题,2. 值类型和引用类型的区别? 3. 什么是装箱和拆箱? 4. 下列代码段中取消装箱操作的是哪一个?请选择一个最佳答案。 A. int x=5;Object o=x; B. int x=5;Console.WriteLine(“The answer is:0”,x); C. int x=5;Object o=x;int y = (int )o; D. short s=5;Object o=s;,课后习题,5. 什么是泛型?为什么要使用泛型? 6. 为什么要使用泛型约束?,81,第三章 托管执行环境,3.1 .概述 3.2 .编辑托管代码 3.3 组织托管代码:程序集 3.4执行托管代码 3.5小结,3.1概述,.NET Framework 中托管代码编译和执行的流程。C# 和VB.NET的代码首先被编译为微软中间语言(Microsoft Intermediate Language,MSIL)并存储在本地。当需要运行这些托管代码时,CLR又对MSIL进行第二次编译(JIT编译),将MSIL代码转换成本机代码(本机代码是针对当前CPU的可执行二进制代码)。 从高级语言编译为公共中间语言的概念是现代编译器技术的主要特征,早在Visual Studio 6.0中,编译器就已经将各种编程语言转换为相同的中间语言,然后使用公共后端将其编译为二进制代码。这种二进制代码针对特定的CPU,只能在兼容的CPU上运行。在 .NET Framework 出现之前,这些二进制代码就是安装在用户计算机上的程序。,3.1概述,图3.1 编译和执行,3.1概述,对于 .NET Framework 应用程序,安装在用户计算机上的程序并不是针对特定的CPU二进制代码,而是此应用程序的MSIL,一种类似于以前隐藏在编译器内部的中间语言的代码。为何要进行这种变化,将代码作为MSIL进行分发有何好处? 很明显,这么做可以实现可移植性。.NET Framework 的核心并不需要在特定的操作系统和CPU上运行,也就是说它可以在非Windows操作系统和非Intel兼容处理器的系统上运行。但是,客观地说,.NET Framework 基本上仍然是侧重于Windows的技术,因此可移植性并不是MSIL的主要目的。,3.2编辑托管代码,3.2.1编辑器的选项 3.2.2Microsoft中间语言 3.2.3元数据 3.2.4 属性,3.2编辑托管代码,编译基于CLR的语言编写的源代码时,生成以MSIL表达的指令和元数据(关于“MSIL指令及其所操作的数据”的一些信息)。无论这些代码一开始是用C# 、VB抑或其他基于CLR的语言编写的,编译器都会将托管代码中的所有类型类、结构、整数、委托及所有其他东西统统转换成MSIL和元数据,该过程如图3.2所示。,3.2编辑托管代码,图3.2中,正被编译的代码包含3个CTS类型,都是类。在使用适当的编译器编译这些代码之后,每一个类都对应于一套等价的MSIL代码,以及描述这些类的元数据。MSIL和元数据都被存储于标准的Windows 可移植可执行(Portable Executable,PE)文件中,可以是DLL文件或EXE文件,常见术语“模块”用于指代这些文件。以下将进一步讨论MSIL和元数据。,3.2编辑托管代码,图3.2 编译托管代码,编辑器选项,.NET Framework 包括一个C# 的命令行编译器,名为csc.exe。 1. 在C# 中编译 要编译一个HelloDemoCS.cs应用程序的源代码,可以在VS的命令窗口中输入如下语句: csc HelloDemoCS.cs 这个命令行调用C# 编译器。此处只需要指定要编译的文件名称,编译器将产生可执行文件HelloDemoCS.exe。,编辑器选项,2.命令还选项 在C# 中,通过使用 /? 开关选项可以获得完整的命令行选项列表,如下所示: csc /? 命令行选项包括:/t 开关,指定编译目标;/r 开关,指定引用程序集;/out 开关,指定输出文件的名称。下面的命令行表示将class1.cs文件编译生成class1.exe文件。 csc /out: c:class1.exe /t:exe c:class1.cs 输出文件的全名称 生成文件的类型 要编译的源文件,编辑器选项,/t 开关中的各个选项及含义如下: /t:exe 控制台应用; /t:winexe Windows Form应用; /t:library 包含清单的程序集; /t:module 不包含清单的独立程序集。,Microsoft中间语言,MSIL与处理器的本机指令集非常相似,但是,并不存在实际执行这些指令的任何硬件;相反,MSIL代码在执行之前总是转换为相应的本机代码。客观地说,在 .NET Framework 环境中进行工作的开发人员并不需要完全理解MSIL,但是,至少要稍微了解一下MSIL的内容。 实际上,MSIL是CLR的汇编语言。关于这些MSIL指令集,值得注意的一点是,它与CLR的CTS抽象有着十分紧密的对应关系。它能直接支持对象、值类型,甚至是装箱和拆箱操作;而且,某些操作(如创建新实例)与高级语言中的一些极为常见的操作符相似,而这些操作方法在典型机器指令中很少见。,Microsoft中间语言,对于希望直接处理那些低级机器码的开发人员,.NET Framework 提供了称为Ilasm的MSIL汇编器。不过,开发人员一般不会去使用此工具,既然可使用更简单、更强大的语言获得相同的结果,就不必用MSIL编写了。,元数据,元数据是一种二进制信息,用以对存储在公共语言运行库的可移植可执行(PE)文件或存储在内存中的程序进行描述。将代码编译为 PE 文件时,便会将元数据插入到该文件的一部分中,而将代码转换为 Microsoft 中间语言 (MSIL) 并将其插入到该文件的另一部分中。在模块或程序集中定义和引用的每个类型和成员都将在元数据中进行说明。当执行代码时,运行库将元数据加载到内存中,并引用它来发现有关代码的类、成员、继承等信息。,元数据,元数据包含以下信息: 类型的名称; 类型的可见性,可为public或assembly; 基类; 所实现的接口; 所实现的方法; 所暴露的属性; 所提供的事件。,元数据,此外,还可以包括更多的细节信息。例如每一个方法的描述,包括方法的参数及其类型,方法的返回值类型等。 Visual Studio 2005使用元数据提供智能感知(IntelliSense)功能,可向开发人员显示对于所输入的类名有哪些相应的方法可用;还可以使用MSIL反汇编工具Ildasm检查模块的元数据,该工具是3.2.2节提到的Ilasm工具的反工具,可提供包含在特定模块中的元数据的详细显示。,属性,. 属性(attribute)是存储在元数据中的值,可以使用属性来全面控制代码的执行方式,它与System.Attribute类相对应。属性(attribute)可添加到类型(如类)以及这些类型的字段、方法和属性(property)中,属性(attribute)是描述代码的代码,而属性(property)是描述对象的代码。.NET Framework 类库依赖于属性(attribute)完成很多事情,包括指定事务要求、指示哪些方法应公开为SOAP可调用的Web服务,以及描述安全性要求。这些属性(attribute)有标准名称和功能,是由使用这些属性(attribute)的 .NET Framework 类库的各个部分所定义的。,属性,开发人员也可以创建自定义的属性(attribute),以一种与应用程序相关的方式来控制行为。为了创建定制的特性,使用基于CLR的编程语言(如C#)时,可以定义一个继承于System.Attribute的类。一旦被编译,该类的一个实例便会自动将其值存储于元数据中。,3.3 组织托管代码:程序集,3.3.1 程序集的元数据:清单 3.3.2 程序集的分类,3.3 组织托管代码:程序集,一个完整的应用程序通常由很多不同的文件组成,某些文件是模块(如DLL文件或EXE文件),其中包含代码,另一些可能包含诸如图形之类的种种资源。在 .NET Framework 应用程序中,构成一个“功能上的逻辑单元”的文件被聚合到一个程序集之中。程序集是开发、部署、运行 .NET Framework 应用程序的基础成分。,程序集的元数据:清单,程序集是一个逻辑上的构件,并不存在单一文件将所有必要文件包裹成一个程序集。实际上,只看磁盘目录列表,不可能说出哪些文件属于同一个程序集。要想搞清楚一个特定的程序集到底由哪些文件构成,必需查看该程序集的清单。如前所述,模块的特性包含了模块内的类型信息,与此相类似,程序集清单包含了“程序集内的所有模块及其他文件”的有关信息,换句话说清单就是程序集的特性,清单包含于程序集的某个文件里,并且包含了程序集的信息,以及“组成程序集的文件”的信息。Visual Studio 这样的工具不但会为每个编译模块生成元数据,也会为每个程序集生成相应清单。,程序集的元数据:清单,一个程序集可由单一文件或一组文件构成。图3.3显示了只包含单个文件的程序集的构成,程序集的元数据、类型元数据、MSIL代码和资源都在一个文件App1.dll中。图3.4显示了包含多个文件的程序集

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论