为了以后复习和查找,花了一些时间整理一下C# 3.0的语言新特性:
一、隐含类型局部变量
var h=23.43
var s="C sharp"
var intArray=new[] {1,2,3,4}
var a=new[] {1,10,100,1000}
注意:
1.var为关键字,可以根据后面的初始化语句自动推断类型。
2.初始化语句必须是表达式,且在编译器可以推断类型。
3.var不是一个类型,也不是类型兼容,可以把它看成一个占位符,编译时会自动替换成一个强类型(不是Object)。
4.var s=null 编译错误(null没类型),编译器不能自动推断s的类型。
5.初始化器不能是一个对象,也不是一个集合,只能是一个表达式,只有根据表达式才能推断它的类型。var s也是不正确的。
6.var 声明的仅限于局部变量,也可以用于foreach,using等语句中。
7.为了避免变量出现var这个变量(var关键字优先),遵循Code Standard规范。
8.数组也可以作为隐含类型。(数组初始化器的类型必须是一致的,编译器不能为不同类型初始化器编译后生成Object[],编译器不能转换,编译错误)
9.它是一个编译时的技术,只能用在local var(函数级)范围。
二、扩展方法
public static void StringTrim(this string s){
..
}
}
string s="Hello,Charles Chen";
s.StringTrim();
编译器编译后会生成Extensions.StringTrim(s);
补充:
class Person{public void Bar(){...}}
Person p=new Person();
p.Bar();
编译器编译后会生成:p.Bar()------>Bar(p)
Class Person{public void Bar(){...}}-------->void Bar(Person this){...}(全局函数)
这就是为什么在实例函数可以访问this指针,静态函数就不能(不是这样编译的)。
这是IL代码的编译过程.(第一阶段编译过程还遵循对象的规范)。
分析S.StringTrim()------>Extensions.stringTrim(S),
我们应该怎样看这个S对象呢?其实从面向对象的角度看是一个调用对象。而编译器看到到了是一个参数,这样从调用对象转换成参数。
从而实现:扩展方法允许我们在不改变源代码的情况下扩展(添加)现有类型中的实例方法。
这样不改变源代码的情况下,增加新的实例方法。注意Extensions必须是静态类.
注意:
1.本质:将实例方法调用在编译期改变为静态类中的静态方法调用。
2.扩展方法的优先级:现有实例方法优先级最高,其次为最近的namespace下静态类中的静态方法,最后为较远的namespace下的静态类的静态方法。(如果2个一样远,则编译error)
3.扩展方法是一种编译时技术,注意与反射等运行时技术进行区别,并慎重使用。
4.当需要对CLR类型进行一些操作,但苦于无法扩展CLR类型的方法,只能创建一些helper方法时,就可以运用扩展方法。
三、对象和集合初始化器
1.对象初始化器
{
int x,y;
public int X{get{return x;} set{x=value;}}
public int Y{get{return y;}set{y=value;}}
}
var a=new Point{X=2,Y=1}
相当于:var a=new Point();a.X=2;a.Y=1;
2.集合初始化器
注意:
1.对象初始化器实际上利用了编译器对对象中对外可见的字段和属性进行按序赋值。
2.集合初始化器会对初始化器中的元素进行按序调用ICollection<T>.Add(T).
3.注意对象的初始化器和集合初始化器中的成员的可见性和调用顺序。
4.对象与集合的初始化器同样是一种编译器技术。
四、匿名类型
var p2=new {Name="Changchang",Sex="男"}
p1=p2
编译后:
{
private string _name;
private string _sex;
public string Name{get;set}
public string Sex{get;set}
}
注意:
1.可以使用new关键字调用匿名初始化器创建的一个匿名类型的对象。
2.匿名类型直接继承自System.Object。
3.匿名类型的成员是编译器根据初始化器推断而来的一些读写属性。
4.局部范围类使用,就可以用匿名类型。
5.在同一段程序(局部范围)内。(2个申明同样的类型在编译后是同一类型。(如上的P1=P2))。