C# 2.0和3.0主要新特性
C# 2.0新特性
C# 2.0引入了很多语言扩展,最重要的就是泛型(Generics)、匿名方法(Anonymous Methods)、迭代器(Iterators)和不完全类型(Partial Types)。
一、泛型
泛型是 2.0 版 C# 语言和公共语言运行库 (CLR) 中的一个新功能。泛型将类型参数的概念引入 .NET Framework,类型参数使得设计如下类和方法成为可能:这些类和方法将一个或多个类型的指定推迟到客户端代码声明并实例化该类或方法的时候。例如,通过使用泛型类型参数 T,您可以编写其他客户端代码能够使用的单个类,而不致引入运行时强制转换或装箱操作的成本或风险,如下所示:
- 使用泛型类型可以最大限度地重用代码、保护类型的安全以及提高性能。
- 泛型最常见的用途是创建集合类。
- .NET Framework 类库在 System.Collections.Generic 命名空间中包含几个新的泛型集合类。应尽可能地使用这些类来代替普通的类,如 System.Collections 命名空间中的 ArrayList。
- 您可以创建自己的泛型接口、泛型类、泛型方法、泛型事件和泛型委托。
- 可以对泛型类进行约束以访问特定数据类型的方法。
- 关于泛型数据类型中使用的类型的信息可在运行时通过反射获取。
二、匿名方法
作为C# 2.0的新特性,匿名方法基本上能够提供与先前命名方法相同的功能,但是它已经不再需要一个在关联到委托之前就明确创建的方法了。
你可以把C# 匿名方法想象为一个实现与委托进行关联这项功能的便捷途径。如果同时看一下匿名方法实现和命名方法实现所取得IL结果,你会发现这两者之间的差别非常小。当编译器碰到匿名方法的时候,它会在类里面创建一个命名方法,并将它与委托进行关联。所以匿名方法在运行期间与命名方法的性能非常类似——性能的增加体现在开发人员的生产效率上,而不是运行期间的执行上。
三、迭代器
迭代器是 C# 2.0 中的新功能。迭代器是方法、get 访问器或运算符,它使您能够在类或结构中支持 foreach 迭代,而不必实现整个 IEnumerable 接口。您只需提供一个迭代器,即可遍历类中的数据结构。当编译器检测到迭代器时,它将自动生成 IEnumerable 或 IEnumerable<T> 接口的 Current、MoveNext 和 Dispose 方法。
- 迭代器是可以返回相同类型的值的有序序列的一段代码。
- 迭代器可用作方法、运算符或 get 访问器的代码体。
- 迭代器代码使用 yield return 语句依次返回每个元素。yield break 将终止迭代。
- 可以在类中实现多个迭代器。每个迭代器都必须像任何类成员一样有唯一的名称,并且可以在 foreach 语句中被客户端代码调用,如下所示:foreach(int x in SampleClass.Iterator2){}
- 迭代器的返回类型必须为 IEnumerable、IEnumerator、IEnumerable<T> 或 IEnumerator<T>。
yield 关键字用于指定返回的值。到达 yield return 语句时,会保存当前位置。下次调用迭代器时将从此位置重新开始执行。
迭代器对集合类特别有用,它提供一种简单的方法来迭代不常用的数据结构(如二进制树)。
四、不完全类型
C#允许在一个代码文件中存放多个类,但这样往往不便于类的管理,所以一向是提倡一个文件中只存放一个类。不过呢,随着类规模的不断膨胀,一个文件中存放一个类也有些显得臃肿,或者是在某个角度上不便于代码的组织。
因此,C# 2.0中引入了不完全类型的概念,即启用了新的修饰符partial。借助该修饰符,我们可以在多个文件中存放一个类,每个文件只包含该类的某些功能。当然,它并不单单可以修饰class,还可以修饰struct和interface。
尽管在一个单一的文件中为一个类型维护所有的源代码是一个良好的编程实践,但有时,一个类型变得非常大,这将成为一个不切实际的限制。此外,程序员经常使用源代码生成器产生应用程序的初始结构,并且修改结果代码。遗憾的是,当源代码在将来被再次发射时,现存的修改将会被覆盖。
不完整类型(partial type)可以让类、结构和接口被拆分成多个部分存储在不同的源文件中,这更利于开发和维护。此外,不完整类型允许某些类型的机器生成的部分与用户编写的部分之间的分离,因此增加由工具产生的代码很容易。
C#3.0新特性
隐含类型局部变量
C# 3.0引进了一个新的关键字叫做"Var"。Var允许你声明一个新变量,它的类型是从用来初始化符变量的表达式里隐式的推断出来的。
var只能作为局部变量使用;
var可以申明任何类型变量,可以根据后面的初始化语句自动推断类型;
var定义时,必须使用表达式初始化;
匿名类型
匿名类型提供了一种方便的方法,可用来将一组只读属性封装到单个对象中,而无需首先显式定义一个类型。
类型名由编译器生成,并且不能在源代码级使用。
匿名类型通常用在查询表达式的select子句中,以便返回源序列中每个对象的属性子集。
匿名类型是使用new 运算符和对象初始值设定项(初始化器)创建的。
匿名类型是由一个或多个公共只读属性组成的类类型。不允许包含其他种类的类成员
也就是说,匿名类型由编译器来推断出一个严格的类型,编译器是可以对其类型进行判定的,只是其类型的名字不由编程者所知而已
扩展方法
扩展方法使你能够使用额外的静态方法来扩展各种类型。不过它们是非常有限的,也只能在实例方法不足够的情况下才作为候补使用。
1、 扩展方法是给现有类型添加一个方法;
2、扩展方法是通过 指定关键字this修饰方法的第一个参数;
3、扩展方法必须声明在静态类中;
4、扩展方法要通用对象来调用;
5、扩展方法可以带参数。
Lambda表达式
在C#2.0中引入了匿名方法,允许在期望出现委托的时候以“内联”的代码替代之。尽管匿名方法提供了函数式编程语言中的很多表达能力,但匿名方法的语法实在是太罗嗦了,并且很不自然。Lambda表达式为书写匿名方法提供了一种更加简单、更加函数化的语法。
实际上Lambda表达式的本质是匿名方法,也即是当编译我们的程序代码时,编译器会自动帮我们将Lambda表达式转换为匿名方法。