话说.net 4.0都出来了,连.net 3.5都还没熟悉,是不是有点落伍阿? 恩 我也这么觉得。为了跟上人类进步的步伐。 今天花了些时间了解了下c#3.5新特性。我认为大致有下面几点新东西:
1、var 关键字
2、自动属性(Automatic property)
3、匿名类
4、扩展方法
当然,话说回来,所有这些c#3.5新特性都是编译器给我们玩的小把戏,也就是人们常说的“语法糖”。在IL级别没有任何变化。
在js中定义变量使用var关键字,可以使用var来定义一个变量,保存任何一种类型的值,但是在C#中只能在声明的时候赋值如:var v = "123";并且只能用作局部变量。不能声明一个var类型的field,或通过方法传递一个var类型的参数等。
自动属性还是有点意思,可以减轻一些工作量:
public string Name
{
get;
set;
}
- 1.
- 2.
- 3.
- 4.
- 5.
是不是有点眼熟呢?呵呵, 不要和抽象属性搞混了,
public abstract string Name
{
get;
set;
}
- 1.
- 2.
- 3.
- 4.
- 5.
C#编译器认得到。利用自动属性,就可以免得定义使用私有成员了,事实上就像我上面说的那样:都是“语法糖” ,在编译成IL的过程中,编译器已经自动为你声明了一个私有成员。那你或许又有疑问了:自动生成的私有成员会不会和你已经有的成员相冲突呢? 恩, 有道理。因为大家都有这样的经历:声明了一个名称为Name的Property就不能声明一个get_Name的方法了,因为在IL中属性是通过方法来实现的。但是现在请放心:自动生成的成员永远不会和你自己的类成员相冲突。
来看下
public string Name
{
get;
set;
}
- 1.
- 2.
- 3.
- 4.
- 5.
生成的IL代码:
.method public hidebysig specialname instance string
get_Name() cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
// Code size 11 (0xb)
.maxstack 1
.locals init (string V_0)
IL_0000: ldarg.0
IL_0001: ldfld string DotNewFeature.TestAutoProperty::'< Name>k__BackingField'
IL_0006: stloc.0
IL_0007: br.s IL_0009
IL_0009: ldloc.0
IL_000a: ret
} // end of method TestAutoProperty::get_Name
.method public hidebysig specialname instance void
set_Name(string 'value') cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
// Code size 8 (0x8)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldarg.1
IL_0002: stfld string DotNewFeature.TestAutoProperty::'< Name>k__BackingField'
IL_0007: ret
} // end of method TestAutoProperty::set_Name
.field private string '< Name>k__BackingField'
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
其中get_Name和set_Name和以前的属性是一样的,不过编译器自动生成了一个 类似< XXXX>k__BackingField的成员,因为包含C#中变量不允许的符号(“< ”,">"),所以在使用的时候还是大可放心的。
那用自动属性和用pulic成员又有啥区别呢?这倒也是,property 好就好在取数和赋值的时候可以执行一些额外的逻辑。而自动属性有没有这些功能。我能想到的有两个原因要使用自动property而不是public field
(1)代码一致性,现在在代码里面基本上看不到使用public field的了
(2)在.Net 中有些地方还只支持property 而不支持public field. 难道不是吗?
当然了,在编写web页面或者web控件的时候最好就不用自动属性了,原因就不用我说了。
匿名类的声明方式如下:
var v = new {name="Ben",age = 5};
string a = v.name;
- 1.
- 2.
编译的时候生成一个范型类,然后调用此范型类的构造函数。具体的就不多说了
至于 扩展方法,他可以给你一种能力,能动态的扩展一个类型的方法。就像js 一样:
Array.prototype.IndexOf = function(index){//....}
- 1.
通过扩展方法 你可在String类中添加你自己的方法 如:OfMyName()
实现方法如下:
namespace MyNameSpace
{
public static class TestStaticMethod
{
public static string OfMyName(this string s)
{
return s + "Ben";
}
}
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
然后在MyNameSpace这个名字空间内都可以这样使用了:
String a ="Hello ";
String b =a. OfMyName();
- 1.
- 2.
当然在IL中还是调用TestStaticMethod.OfMyName的。所以还是编译器耍的障眼法。不过不要真的被迷惑了,请看下面的代码:
namespace MyNameSpace
{
public static class TestStaticMethod
{
public static string OfMyName(this string s)
{
return s + "Ben";
}
}
//新加的一个静态类,其中也包含OfMyName方法
public static class TestStaticMethod_2
{
public static string OfMyName(this string s)
{
return s + "Benjamin";
}
}
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
然后调用:
String a ="Hello ";
String b =a. OfMyName();
结果会增么样呢?
编译失败!!! 因为在 IL中还是把a. OfMyName()映射到具体的类中的方法,而现在不知道要去调用TestStaticMethod.OfMyName 还是TestStaticMethod_2.OfMyName。
C#3.5新特性就给大家介绍到这里了。
【编辑推荐】