vs2010正式版4月12日发布了,前几天我也下了一个,但这几天都没有时间好好试用一下,今天针对C#语言的新特性使用了一下,感觉还不错,有几个新特性和大家分享一下,希望我没有太火星……
一、新关键词——dynamic
在新版本的C#中,dynamic关键词是一个很重要的新特性,现在你可以创建动态对象并在运行时再决定它的类型。而且.net 4.0为CLR加入了一组为动态语言服务的运行时环境,称为DLR(Dynamic Language Runtime动态语言运行时),这使得C#这种静态类型语言可以在 .NET Framework 中开发动态语言并为与其它动态语言提供互操作性了。DLR架构见下图:
关于DLR的更详细信息,可以参考msdn:http://msdn.microsoft.com/en-us/library/dd233052(VS.100).aspx
先来看看dynamic的一个例子:
- C# code
-
dynamic dyn = 1; Console.WriteLine(dyn.GetType()); dyn = 1.234; Console.WriteLine(dyn.GetType()); dyn = "ojlovecd"; Console.WriteLine(dyn.GetType()); /* 输出: System.Int32 System.Double System.String */
可能你会说,这个效果,我用object关键字就可以了,干吗加个dynamic?那我们就来讨论一下object与dynamic的区别。
先看如下代码:
- C# code
-
object obj = 10; obj = obj + 10;
这样肯定是通不过编译的,虽然obj存储的是一个整形,但是如果不进行类型转换的话编辑器肯定是不会编译通过的。所以我们就要改成:
- C# code
-
object obj = 10; obj = (int)obj + 10;
但是这样就有个类型安全的问题了,假如我类型不是转换成int,而是string,那么编译器一样可以编译通过,但是运行时就会抛出异常:
- C# code
-
object obj = 10; obj = (string)obj + 10; /* Unhandled Exception: System.InvalidCastException: Unable to cast object of type 'System.Int32' to type 'System.String'. */
由此可见,你要使上面代码正确运行,你必须得正确的进行类型的显式转换,就仅仅因为不这样做的话,编译器不让你通过而已。为了解决这个问题,dynamic由此产生。它告诉编译器:“哥说啥就是啥,你甭跟我废话”。见下例:
- C# code
-
dynamic dyn = 10; dyn = dyn + 10; Console.WriteLine(dyn); dyn = 10.02; dyn = dyn + 10; Console.WriteLine(dyn); dyn = "ojlovecd"; dyn = dyn + 10; Console.WriteLine(dyn);
这是object和dynamic的其中一个不同。它告诉编译器对象的类型只有在运行时才知道,编译器就不会对其进行干涉。这样你可以少写很多代码。但有一点必须强调一下:dynamic并没有增加或减少危险。当你操作对象时要用到的所有类型检查技巧(例如反射),在动态对象中一样要用到。例如,以下代码在运行时将会抛出异常:
- C# code
-
dynamic dyn = 10; dyn = dyn + DateTime.Now; Console.WriteLine(dyn); /* Unhandled Exception: Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: Oper ator '+' cannot be applied to operands of type 'int' and 'System.DateTime' at CallSite.Target(Closure , CallSite , Object , DateTime ) at System.Dynamic.UpdateDelegates.UpdateAndExecute2[T0,T1,TRet](CallSite site , T0 arg0, T1 arg1) at ConsoleApplication3.Program.Main(String[] args) in D:\CSharpProj\ConsoleAp plication3\ConsoleApplication3\Program.cs:line 26 */
二、可选(或默认)参数
貌似这个特性在C#1.0就已经有很多人问过了,但直到4.0才有。现在你可以在方法定义的时候为参数指定一个默认值。调用方法的时候既可以像平时那样传入参数,也可以直接跳过不传入,这样的话,就使用默认值传到方法里。例如:
- C# code
-
static void Main(string[] args) { TestMethod(); TestMethod(3); } static void TestMethod(int i = 10) { Console.WriteLine(i); }
值得注意一点的是,可选参数必须放在所有参数的最后。这里就有个问题了,假如我某个方法有两个参数,两个都是可选参数,而我调用的时候只想传入第二个参数,怎么办呢?我们来试试。
- C# code
-
static void Main(string[] args) { TestMethod("hello"); } static void TestMethod(int i = 10, string s = "ojlovecd") { Console.WriteLine("i:{0},s:{1}", i, s); }
但很可惜,编译通不过,这个问题,利用下面的新特性就可以解决了。
三、命名参数
在之前版本的C#中,方法定义的参数顺序必须与方法调用时的参数顺序一致,即方法Method(int i, string s)调用时就必须第一个传入int,第二个传入string,而现在,这个规矩可以被打破了。你可以自己随便什么顺序传入,这也在一定程度上提高了代码的可读性。例子:
- C# code
-
static void Main(string[] args) { TestMethod2(s: "ojlovecd", i: 26); } static void TestMethod2(int i, string s) { Console.WriteLine("i:{0},s:{1}", i, s); }
这样一来,上面的那个问题就可以迎刃而解了:
- C# code
-
static void Main(string[] args) { TestMethod(s: "hello"); } static void TestMethod(int i = 10, string s = "ojlovecd") { Console.WriteLine("i:{0},s:{1}", i, s); }
四、提高COM的互操作性
基于以上三点新特性,COM的互操作性也被提高了。以后不用再写如下丑陋的代码:
- C# code
-
var excelApp = new Excel.Application(); // . . . excelApp.get_Range("A1", "B4").AutoFormat( Excel.XlRangeAutoFormat.xlRangeAutoFormatTable3, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
现在只需这么写就搞定了:
- C# code
-
excelApp.Range["A1", "B3"].AutoFormat( Excel.XlRangeAutoFormat.xlRangeAutoFormatClassic2);
顺带一句,这段代码用到了另一个叫做“索引属性”的新特性,更多关于这个特性的信息可以参考http://msdn.microsoft.com/en-us/library/ee310208%28VS.100%29.aspx 这个特性只能用于COM互操作上,你不能创建自己的索引属性。
好了,就先分享这么多吧,以后有什么新发现再与大家分享吧~~~

学习
支持~
Very Good!
学习了,呵
接分听讲,感谢分享!
学习了……………
学习,谢谢
good
study~~~~~~~~~
非常不错
支持~
dddddddddddddddddd
又得学习了,哥还在2.0上爬呢,哈哈
性能怎么样呢???
top top top
学习学习
好好学习,天天向上!!!!!!!!!!
学习。。。
看了一下LZ的介绍,收获不少呀,dynamic暂时没有想到具体的情况,一定用他才能解决。不过可选参数以及命名参数真的挺有用。向LZ学习了!
3q
学习了
C#变得好厉害了啊
每天回帖
学习下~~
值得学习
谢谢!受教了
C#向N多语言借鉴了经验,希望越来越强大,越来越方便。感谢lz分享,学习了。
接分,补充下:C# 4.0 支持更高级的Lambda表达式。
C#4真的那么好吗,稳定吗?
学习了!
好好学下
看了一下LZ的介绍,收获不少呀,dynamic暂时没有想到具体的情况,一定用他才能解决。不过可选参数以及命名参数真的挺有用。向LZ学习了!我忘了介绍了,配合System.Dynamic命名空间下的ExpandoObject类,实现动态语言编程真是太方便了,举个例子:C# code
dynamic obj = new ExpandoObject();
obj.Name = "ojlovecd";
obj.Age = 26;
obj.ShowInfo = new Action<dynamic>(dyn => { Console.WriteLine("Name:{0},Age:{1}", dyn.Name, dyn.Age); });
obj.ShowInfo(obj);
不懂.Net为什么不用variant作为关键字?还是说variant已经是关键字了?dynamic是从哪里学来的?
好东西啊
不懂.Net为什么不用variant作为关键字?还是说variant已经是关键字了?dynamic是从哪里学来的?从C#3.0开始就已经有var关键字了
variant 不是 var也可能是怕混淆?
理解得比较透撤的呢,学习一下
路过看看了。。。
学习。。。。
学习了~~~
只接分不发言
楼主写得简单易懂,让人很容易理解,不知您可出什么书没?谢谢分享!
这个厉害呀,我写什么属性,他就有什么属性,方便!我忘了介绍了,配合System.Dynamic命名空间下的ExpandoObject类,实现动态语言编程真是太方便了,举个例子:C# code dynamic obj = ne……
看来Dynamic向动态语言学习了不少。
这个厉害呀,我写什么属性,他就有什么属性,方便!是的,我刚开始用的时候也吃了一惊,一开始我以为只能生成动态属性,没想到连方法都可以动态生成。C#3.0的linq+lambda就已经够强大了,再加上4.0的dynamic,C#已经可以像javascript般使用了
楼主写得简单易懂,让人很容易理解,不知您可出什么书没?谢谢分享!感谢关注,正在考虑写一个关于C#的书籍,但不知道出版商会不会看上……
学习了~
顶……….
学习,谢谢
木娄 主主 人尔 女子 木奉
这个很老了耶……不是吗?
VB.net有没有类似的改进
不错的 过来学习的了
看看!
进来YM一下~
看了一下LZ的介绍,收获不少呀,dynamic暂时没有想到具体的情况,一定用他才能解决。不过可选参数以及命名参数真的挺有用。向LZ学习了!我忘了介绍了,配合System.Dynamic命名空间下的ExpandoObject类,实现动态语言编程真是太方便了,举个例子:C# code dynamic obj = ……其实没什么可以吃惊的,不过就是把反射的语法简化了。另外 var 不是 VB 和 COM 里面那种 variant。其实 var 还是确定的类型,不过是交给编译器自动推定了而已。如同匿名类、匿名方法也并非真的没有名字,而是编译器自动去识别了。
xuexixuexi
very good 学习中
very good 学习中
值得学习!
学习中。。。
1.xButton btn=new Button();btn.OnClick+=new EventHandler(btn_Click);private void btn_Click(object sender,EventArgs e){}2.0Button btn=new Button();btn.OnClick+=delegate(object sender,EventArgs e){};3.0Button btn=new Button();btn.OnClick+=(sender,e)=>{};
学习中。。。
学习 学习
很好,与时俱进!
。。。怎么那么强悍啊!
又要学习了 看来这速度就是快!
我们这次参加的esri竞赛,老师就要我们用C#4.0开发~看来还是不错的。LZ介绍很好,学习了不少
但愿是一次成功的升级
关于命名参数的问题: static void Main(string[] args) { TestMethod(s: "hello");//这里必须写s吗?可不可以随便写个名字? } static void TestMethod(int i = 10, string s = "ojlovecd") { Console.WriteLine("i:{0},s:{1}", i, s); } ps:msdn我还没看。。。
学习学习!
很好 学习学习
学习 学习
有时间研究研究
哎“`我3.0还没学好呢!
不错不错可是我还在用2.0呀!不过还是学习了谢谢
STUDY,TKS
mark
唉 需要学习的还很多
Thank you!
学习终于有默认参数了
没想明白三、命名参数当类的构造函数或者方法的重载有很多个的时候而且参数类型和名称都一样,那用这个 命名参数编译器怎么知道该调用哪个呢?
帮顶““`
新特性了解下
第三点 参数命名TestMethod(s: "hello");只要调入一个参数 static void TestMethod(int i = 10, string s = "ojlovecd") { Console.WriteLine("i:{0},s:{1}", i, s); } 这里却有2个参数,怎么调入呢。 这个与它传入参数的顺序可以随意有什么关系呢
学习……
学习……
学习,帮顶
学习!~~
1.这里与传入的参数顺序没应该没关系吧,这就是4.0特性;2.TestMethod(s: "hello");表示第一个参数没传入,是因为默认定义了int i=103.TestMethod(s: "hello");中的s与static void TestMethod(int i = 10, string s = "ojlovecd")中string s="";是对应的;
学习了,谢谢
空军来轰炸了,招家伙。
学习…
1.这里与传入的参数顺序没应该没关系吧,这就是4.0特性;2.TestMethod(s: "hello");表示第一个参数没传入,是因为默认定义了int i=103.TestMethod(s: "hello");中的s与static void TestMethod(int i = 10, string s = "ojlovecd")中string s="";是对应的;应该是这样,很容易想明白的!
不错,学习