C_3.0新特性.0%d0%c2%cc%d8%d0%d4.ppt_第1页
C_3.0新特性.0%d0%c2%cc%d8%d0%d4.ppt_第2页
C_3.0新特性.0%d0%c2%cc%d8%d0%d4.ppt_第3页
C_3.0新特性.0%d0%c2%cc%d8%d0%d4.ppt_第4页
C_3.0新特性.0%d0%c2%cc%d8%d0%d4.ppt_第5页
已阅读5页,还剩28页未读 继续免费阅读

下载本文档

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

文档简介

C#3.0新特性,C#3.0新特性,泛型集合隐式类型的本地变量和数组自动实现的属性对象初始值设定项集合初始值设定项匿名类型扩展方法分部方法定义Lambda表达式,泛型集合,在.NET2.0之前,不存在泛型,主要可以通过以下两种方式实现集合:(1)使用ArrayList直接将对象放入ArrayList,操作直观,但由于集合中的项是Object类型,因此每次使用都必须进行繁琐的类型转换。(2)使用自定义集合类。比较常见的做法是从CollectionBase抽象类继承一个自定义类,通过对IList对象进行封装实现强类型集合。这种方式要求为每种集合类型写一个相应的自定义类,工作量较大。泛型集合的出现较好的解决了上述问题,现在泛型集合类通常是集合的首选类型。泛型允许将类名作为参数传递给泛型类型,并生成相应的对象。主要利用System.Collections.Generic命名空间下面的List泛型类创建集合。语法如下:ListListOfT=newList();其中的T就是所要使用的类型,既可以是简单类型,如string、int,也可以是用户自定义类型。建议面向2.0版的所有应用程序都使用新的泛型集合类,而不要使用旧的非泛型集合类,如ArrayList。,泛型优点,在公共语言运行库和C#语言的早期版本中,通用化是通过在类型与通用基类型Object之间进行强制转换来实现的,泛型提供了针对这种限制的解决方案。通过创建泛型类,您可以创建一个在编译时类型安全的集合。使用非泛型集合类的限制可以通过编写一小段程序来演示,该程序利用.NETFramework类库中的ArrayList集合类。ArrayList是一个使用起来非常方便的集合类,无需进行修改即可用来存储任何引用或值类型。,System.Collections.ArrayListlist1=newSystem.Collections.ArrayList();list1.Add(3);list1.Add(105);System.Collections.ArrayListlist2=newSystem.Collections.ArrayList();list2.Add(ItisraininginRedmond.);list2.Add(Itissnowinginthemountains.);,泛型优点,但这种方便是需要付出代价的。添加到ArrayList中的任何引用或值类型都将隐式地向上强制转换为Object。如果项是值类型,则必须在将其添加到列表中时进行装箱操作,在检索时进行取消装箱操作。强制转换以及装箱和取消装箱操作都会降低性能;在必须对大型集合进行循环访问的情况下,装箱和取消装箱的影响非常明显。另一个限制是缺少编译时类型检查;因为ArrayList会将所有项都强制转换为Object,所以在编译时无法防止客户端代码执行类似如下的操作:,System.Collections.ArrayListlist=newSystem.Collections.ArrayList();list.Add(3);list.Add(ItisraininginRedmond.);intt=0;foreach(intxinlist)t+=x;,泛型优点,而泛型将不再需要向上强制转换为T:System.Object,同时,也使得编译器可以进行类型检查。换句话说,ArrayList需要一个类型参数。这正是泛型所能提供的。在:System.Collections.Generic命名空间的泛型List(T)集合中,向集合添加项的操作类似于以下形式:,Listlist1=newList();list1.Add(3);list1.Add(105);Listlist2=newList();list2.Add(ItisraininginRedmond.);list2.Add(Itissnowinginthemountains.);,隐式类型的本地变量,varintValue=5;varstringValue=Thisisastring;varcustomClass=newLocalVariables();varanon=newName=Terry,Age=34;varlist=newList();varexpr=fromcincustomerswherec.City=Londonselectc;,这个特性非常简单,有些JavaScript的影子,我们可以统一使用使用var关键字来声明局部变量,而不再需要指明变量的确切类型了,变量的确切类型可通过声明变量时的初始值推断出来。这样一来,可以大大简化我们声明局部变量的工作量了,下面是一个例子:,要特别注意的是,由于变量的类型是通过变量初始值推断而来的,所以在声明变量的同时必须为变量指定初始值。并且,变量并不是没有类型的,变量一旦初始化之后,类型就确定下来了,以后就只能存储某种类型的值了,比如上面的stringValue的类型经推断为string,所以该变量就只能保存string类型的值了。,隐式类型的本地变量,varintValue=5;varstringValue=Thisisastring;varcustomClass=newLocalVariables();varanon=newName=Terry,Age=34;varlist=newList();varexpr=fromcincustomerswherec.City=Londonselectc;,这个特性非常简单,有些JavaScript的影子,我们可以统一使用var关键字来声明局部变量,而不再需要指明变量的确切类型了,变量的确切类型可通过声明变量时的初始值推断出来。这样一来,可以大大简化我们声明局部变量的工作量了,下面是一个例子:,要特别注意的是,由于变量的类型是通过变量初始值推断而来的,所以在声明变量的同时必须为变量指定初始值。并且,变量并不是没有类型的,变量一旦初始化之后,类型就确定下来了,以后就只能存储某种类型的值了,比如上面的stringValue的类型经推断为string,所以该变量就只能保存string类型的值了。,1.局部变量可以用var声明2.var是推断“类型”,不是显式类型3.var关键字指示编译器根据初始化语句右侧的表达式推断变量的类型,隐式类型的本地数组,inta=newint1,10,100,1000;/intstringb=newstringhello,null,world;intc=newintnewint1,2,3,4,newint5,6,7,8;stringd=newstringnewstringLuca,Mads,Luke,Dinesh,newstringKaren,Suma,Frances;,隐式类型的本地数组,vara=new1,10,100,1000;/intvarb=newhello,null,world;/string型的数组使用方括号varc=newnew1,2,3,4,new5,6,7,8;vard=newnewLuca,Mads,Luke,Dinesh,newKaren,Suma,Frances;,1.没有在初始化语句的左侧对隐式类型的数组使用方括号2.交错数组就像一维数组那样使用new进行初始化3.不支持隐式类型的多维数组,自动实现的属性,使用对象初始值设定项可以在创建对象时向对象的任当属性访问器中不需要其他逻辑时,自动实现的属性可使属性声明变得更加简洁何可访问的字段或属性分配值,而无需显式调用构造函数。,自动实现的属性,/C#2.0publicclassPersonprivatestring_firstName,privatestring_lastName;privateint_age;publicstringFirstNamegetreturn_firstName;set_firstName=value;publicstringLastNamegetreturn_lastName;set_lastName=value;publicintAgegetreturn_age;set_age=value;,/C#3.0publicclassPersonpublicstringFirstNameget;set;publicstringLastNameget;set;publicintAgeget;set;,对象初始值设定值,使用对象初始值设定项可以在创建对象时向对象的任何可访问的字段或属性分配值,而无需显式调用构造函数。,staticvoidMain(stringargs)catx=newcatname=fd,age=1;publicclasscatpublicstringnameget;set;publicintageget;set;,集合初始值设定项,1.使用集合初始值设定项可以在初始化一个实现了IEnumerable的集合类时指定一个或多个元素初始值设定项。2.元素初始值设定项可以是简单的值,也可以是表达式或对象初始值设定项3.通过使用集合初始值设定项,无需在源代码中指定多个对该类的Add方法的调用;编译器会添加这些调用。,Listdigits=newList0,1,2,3,4,5,6,7,8,9;Listdigits2=newList0+1,12%3,MakeInt();,集合初始值设定项,/范例1Listpeople=newList();people.Add(newPerson()FirstName=Bart,LastName=Simpson,Age=12);people.Add(newPerson()FirstName=Clark,LastName=Kent,Age=35);people.Add(newPerson()FirstName=Peter,LastName=Parker,Age=30);,/范例2varpeople=newList()newPerson()FirstName=Bart,LastName=Simpson,Age=12,newPerson()FirstName=Clark,LastName=Kent,Age=35,newPerson()FirstName=Peter,LastName=Parker,Age=30;,匿名类型,在面向对象编程中,类class是定义和描述对象的蓝图,类通常包含了字段、方法、事件、属性等成员,因此类的定义通常需要一定的代码。一般情况下,我们先定义好类,然后再用该类来创建一个该类的实例对象。但是,在某些情况下,一些类仅包含了字段,而不包含任何方法、事件的定义,这样的类通常仅仅用来表示对数据的封装。如果这样的类只是临时使用一下,或者在局部使用一下,那么定义该类的代码就显得冗长和繁琐。现在,C#3.0中的匿名类型特性就可以很好的解决上面提到的问题,通过匿名类型,我们可以简单使用new属性名1=值1,属性名2=值2,.,属性名n=值n的形式直接在函数中创建新的类型,看下面这个例子:,varstudent=newID=100,Name=”Tom”,Scores=newint99,98,78;,匿名类型,1.匿名类型提供了一种方便的方法,可用来将一组只读属性封装到单个对象中,而无需首先显式定义一个类型。2.类型名由编译器生成,并且不能在源代码级使用。3.这些属性的类型由编译器推断varv=newAmount=108,Message=Hello;4.匿名类型通常用在查询表达式的select子句中,以便返回源序列中每个对象的属性子集5.匿名类型是使用new运算符和对象初始值设定项创建的6.匿名类型是由一个或多个公共只读属性组成的类类型。不允许包含其他种类的类成员(如方法或事件)。,扩展方法,扩展方法使您能够向现有类型“添加”方法,而无需创建新的派生类型、重新编译或以其他方式修改原始类型扩展方法是一种特殊的静态方法,但可以像扩展类型上的实例方法一样进行调用。对于用C#和VisualBasic编写的客户端代码,调用扩展方法与调用在类型中实际定义的方法之间没有明显的差异,扩展方法,最常见的扩展方法是LINQ标准查询运算符它们向现有的System.Collections.IEnumerable和SystemCollectionsGenericIEnumerable(T)类型添加了查询功能,classExtensionMethods2staticvoidMain()intints=10,45,15,39,21,26;varresult=ints.OrderBy(g=g);foreach(variinresult)System.Console.Write(i+);/Output:101521263945,扩展方法,扩展方法被定义为静态方法,但它们是通过实例方法语法进行调用的。它们的第一个参数指定该方法作用于哪个类型,且该参数以this修饰符为前缀。仅当您使用using指令将命名空间显式导入到源代码中之后,扩展方法才位于范围中请注意,它是在非嵌套、非泛型静态类内部定义的,扩展方法示例,namespaceExtensionMethodspublicstaticclassMyExtensionspublicstaticintWordCount(thisStringstr)returnstr.Split(newchar,.,?,StringSplitOptions.RemoveEmptyEntries).Length;,usingExtensionMethods;strings=HelloExtensionMethods;inti=s.WordCount();,扩展方法说明,扩展方法编译器生成的中间语言(IL)会将代码转换为对静态方法的调用。因此,并未真正违反封装原则。实际上,扩展方法无法访问它们所扩展的类型中的私有变量。在编译时绑定扩展方法可以使用扩展方法来扩展类或接口,但不能重写扩展方法。与接口或类方法具有相同名称和签名的扩展方法永远不会被调用。编译时,扩展方法的优先级总是比类型本身中定义的实例方法低。换句话说,如果某个类型具有一个名为Process(inti)的方法,而您有一个具有相同签名的扩展方法,则编译器总是绑定到该实例方法。当编译器遇到方法调用时,它首先在该类型的实例方法中寻找匹配的方法。如果未找到任何匹配方法,编译器将搜索为该类型定义的任何扩展方法,并且绑定到它找到的第一个扩展方法,分部方法定义,分部类或结构可以包含分部方法。类的一个部分包含方法的签名。可以在同一部分或另一个部分中定义可选实现。如果未提供该实现,则会在编译时移除方法以及对方法的所有调用。分部方法使类的某个部分的实施者能够定义方法(类似于事件)。类的另一部分的实施者可以决定是否实现该方法。如果调用了未实现的方法,将不会导致编译时错误或运行时错误。在自定义生成的代码时,分部方法特别有用。这些方法允许保留方法名称和签名,因此生成的代码可以调用方法,而开发人员可以决定是否实现方法。不会产生运行时开销。分部方法声明由两个部分组成:定义和实现。它们可以位于分部类的不同部分中,也可以位于同一部分中。如果不存在实现声明,则编译器将优化定义声明和对方法的所有调用,分部方法定义,1.分部方法声明必须以上下文关键字partial开头,并且方法必须返回void。2.分部方法可以有ref参数,但不能有out参数。3.分部方法为隐式private方法,因此不能为virtual方法。4.分部方法不能为extern方法,因为主体的存在确定了方法是在定义还是在实现。5.分部方法可以有static和unsafe修饰符。6.分部方法可以为泛型的。约束将放在定义分部方法声明上,但也可以选择重复放在实现声明上。参数和类型参数名称在实现声明和定义声明中不必相同。7.不能将委托转换为分部方法。,/Definitioninfile1.cspartialvoidonNameChanged();/Implementationinfile2.cspartialvoidonNameChanged()/methodbody,委托,委托是一种引用方法的类型。一旦为委托分配了方法,委托将与该方法具有完全相同的行为。委托方法的调用可以像其他任何方法一样,具有参数和返回值,如下面的示例所示:publicdelegateintPerformCalculation(intx,inty);与委托的签名(由返回类型和参数组成)匹配的任何可访问类或结构中的任何方法都可以分配给该委托。方法可以是静态方法,也可以是实例方法。这样就可以通过编程方式来更改方法调用,还可以向现有类中插入新代码。只要知道委托的签名,便可以分配自己的委托方法。,classTestdelegatevoidTestDelegate(strings);staticvoidM(strings)Console.WriteLine(s);staticvoidMain(stringargs)TestDelegatetestdelA=newTestDelegate(M);/C#1.0/C#2.0:TestDelegatetestDelB=delegate(strings)Console.WriteLine(s);/C#3.0.TestDelegatetestDelC=(x)=Console.WriteLine(x);testdelA(Hello.MynameisMandIwritelines.);testDelB(Thatsnothing.Imanonymousand);testDelC(Imafamousauthor.);Console.WriteLine(Pressanykeytoexit.);Console.ReadKey();,/*Output:Hello.MynameisMandIwritelines.Thatsnothing.ImanonymousandImafamousauthor.Pressanykeytoexit.*/,匿名方法,在2.0之前的C#版本中,声明委托的唯一方法是使用命名方法。C#2.0引入了匿名方法,而在C#3.0及更高版本中,Lambda表达式取代了匿名方法,作为编写内联代码的首选方式。,delegatevoidTestDelegate(strings);/C#2.0:TestDelegatetestDelB=delegate(strings)Console.WriteLine(s);/C#1.0TestDelegatetestdelA=newTestDelegate(M);staticvoidM(strings)Console.WriteLine(s);,Lambda表达式,“Lambda表达式”是一个匿名函数,它可以包含表达式和语句,并且可用于创建委托或表达式目录树类型。所有Lambda表达式都使用Lambda运算符=,该运算符读为“goesto”。该Lambda运算符的左边是输入参数(如果有),右边包含表达式或语句块。Lambda表达式x=x*x读作“xgoestox乘以x”,delegateintdel(inti);delmyDelegate=x=x*x;intj=myDelegate(5);/j=25将此表达式分配给委托类型,usingSystem.Linq.Expressions;/.Expression=x=x*x;创建表达式目录树类型,Lambda表达式,采用Lambda表达式TestDelegatetestDelC=(x)=Console.WriteLine(x);采用匿名函数TestDelegatetestDelC=delegate(stringx)Console.WriteLine(x);以上两种实现方法结果一致,Lambda表达式,在is或as运算符的左侧不允许使用Lambda适用于匿名方法的所有限制也适用于Lambda表达式Lambda表达式返回表达式的结果,并采用以下基本形式,(inputparameters)=expression(x,y)=x=y(intx,strings)=s.Lengthx()=SomeMethod(),只有在Lambda有一个输入参数时,括号才是可选的;否则括号是必需的。两个或更多输入。参数由括在括号中的逗号分隔。编译器难于或无法推断输入类型,则使用显式指定类型使用空括号指定零个输入参数Lambda表达式的主体可以包含方法调用,Lambda语句,Lambda语句与Lambda表达式类似,只是语句括在大括号中(inputparameters)=statemen

温馨提示

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

评论

0/150

提交评论