第1讲:概览
2007.4.13 李建忠
C# 3.0语言主要增强
隐含类型局部变量
扩展方法
对象与集合初始化器
匿名类型
Lambda表达式
查询表达式(LINQ)
表达式树
隐含类型局部变量
var为关键字,可以根据后面的初始化语句自动推断类型。
初始化语句必须为表达式,且编译时可以推断类型。
var不是一个类型,它实际上可以看作一个占位符,只是在编程上起一个文法的作用,编译器在随后就会把它替代为一个具体的强类型,而不是object。var的右边表达式不能为null,因为编译器无法通过null推断类型。
var声明的仅限于局部变量,亦可以用于foreach,using等语句中。
如果我们有一个类型较var,那么我们自己定义的var类型将作为优先使用的类型,作为隐含类型的var次之。
数组也可以作为隐含类型。
数组元素要求类型统一,如果是一个int一个string,那么编译时会报错,编译器不会讲数组定义为object类型。
隐含类型局部变量的这些小技巧可以提高我们代码的复用程度,和代码的抽象性。
扩展方法
扩展方法允许我们在不改变源代码的情况下扩展(即添加)现有类型中的实例方法。
参数中this关键字会告诉编译器,这个方法是一个扩展方法。将来调用s.Foo()会被转换为:Extensions.Foo(s),由实例方法转换为静态方法。
p.Bar()这个方法调用在被编译的时候,Bar方法虽然没有参数,但是它会被编译为传入它所在实例的含参方法,即this指针。编译器在IL代码编译(第二阶段编译)的时候根本就不去区分对象、静态函数、实例函数等等,所有的东西都是全局函数。
扩展方法看起来像是方法s的调用对象是Foo,其实在编译器看来,所有东西都是方法的参数,会把调用对象转换为参数。
这种扩展和继承的扩展不一样,继承的扩展既可以增加也可以override更改,而这种扩展只能增加,不能修改。
扩展方法要点
扩展方法的本质为将实例方法调用在编译期改变为静态类中的静态方法调用。
注意扩展方法的优先级:现有实例方法优先级最高,其次为最近的namespace下的静态类的静态方法,最后为较远的namespace下的静态类的静态方法。
扩展方法是一种编译时技术,注意与反射等运行时技术进行区别,并慎重使用。
对象与集合初始化器
对象与集合初始化器要点
对象初始化器实际上利用了编译器对对象中对外可见的字段和属性进行按序赋值。
集合初始化器会对初始化器中的元素进行按序调用ICollection<T>.Add(T)。
注意对象初始化器和集合初始化器中成员的可见性和调用顺序。
对象与集合初始化器同样是一种编译时技术。
匿名类型
可以使用new关键字调用匿名初始化器创建一个匿名类型的对象。
匿名类型直接继承自System.Object。
匿名类型的成员是编译器根据初始化器推断而来的一些读写属性。
编译器会自动推导出以上的类以及一个构造函数,由使用来推断,这种匿名类型适用于局部地方的引用。
如果同一段程序中,匿名类型p1和p2指定的属性名称和序列都相同,那么它们都是指向的同一个匿名类型,编译器为它们生成的类型名都一样,这样它们就可以互相赋值。
2010.11.3