一、隐含类型局部变量
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))。
初识Lambda表达式:
使用C# 2.0中的匿名方法查找"内部包含abc子串的所有字符串":
delegate(string s){
return s.Indexof("abc")>0}
)
使用C# 3.0中的Lambda表达式查找"内部包含abc子串的所有字符串":
Lambda表达式简介
为什么Lambda表达式比匿名方法更好?
C# 2.0的匿名方法允许我们以内联的方式来实现委托实例,而C# 3.0的Lambda表达式运行我们使用一种更接近人的思维,更自然的方式来实现类似于匿名方法同样的效果。
Lambda表达式格式
(参数列表)=>表达式或者语句块
可以有多个参数,一个参数,或者无参数。参数类型可以隐式或者显式。例如:
x=>x*10 //单参数,隐式类型=>表达式
x=>{return x*10} //单参数,隐式类型=>语句块
(int x) => x*10 //单参数,显式类型=>表达式
(int x) =>{return x*10} //单参数,显示类型=>语句块
()=>{Console.WriteLine()}//无参数
注意:
1.Lambda表达式的参数类型可以省略,因为可以根据使用上下文进行推测。
2.Lambda表达式的主体(body)可以是表达式,也可以是语句块。
3.Lambda表达式传入的实参将参与类型推断,以及方法重载辨析。
4.Lambda表达式表达式和表达式体可以被转换成表达式树。
Lambda表达式与委托类型
Lambda表达式L可以被转换成委托类型D,需要满足以下条件:
1.L和D拥有相同的参数个数
2.L参数类型要与D参数类型相同。注意隐式类型要参与类型辨析。
3.D的返回类型与L相同,无论L是表达式,还是语句块。
转自http://www.cnblogs.com/Charles2008/archive/2009/04/19/1439167.html
浙公网安备 33010602011771号