博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

C#4.0 新特性

Posted on 2012-02-21 14:10  十一郞  阅读(179)  评论(0编辑  收藏  举报

C#4.0增加了动态语言的特性,从里面可以看到很多javascript、python这些动态语言的影子。虽然越来越偏离静态语言的道路,但从另一个角度来说,这些特性也都是为了提高程序员的生产力。

 

概述

  回顾C#发展的历史,C#1.0完全是模仿Java,并保留了C/C++的一些特性如struct,新学者很容易上手;C#2.0加入了泛型,也与Java1.5的泛型如出一辙;C#3.0加入了一堆语法糖,并在没有修改CLR的情况下引入了Linq,简直是神来之笔,虽然很多项目出于各种各样如性能之类的原因没有采用,但非常适合小型程序的快速开发,减轻了程序员的工作量,也提高了代码的可读性;C#4.0增加了动态语言的特性,从里面可以看到很多javascript、python这些动态语言的影子。从另一个角度来说,这些特性也都是为了提高程序员的生产力。
 

新特性

Dynamically Typed Object

  C#4.0加入了dynamic关键字,可以申明一个变量的static类型为dynamic。
 
  在3.0及之前,如果你不知道一个变量的类型,而要去调用它的一个方法,一般会用到反射:
 
  object calc = GetCalculator();
 
  Type calcType = calc.GetType();
 
  object res = calcType.InvokeMember("Add",BindingFlags.InvokeMethod, null,new object[] { 10, 20 });int sum = Convert.ToInt32(res);
 
  有了dynamic,就可以把上面代码简化为:
 
  dynamic calc = GetCalculator();
 
  int sum = calc.Add(10, 20);
 
  使用dynamic的好处在于,可以不去关心对象是来源于COM, IronPython, HTML DOM或者反射,只要知道有什么方法可以调用就可以了,剩下的工作可以留给runtime。
 
  dynamic也可以用在变量的传递中,runtime会自动选择一个最匹配的overload方法。
 
  这里有一个demo:把一段javascript代码拷到C#文件中,将var改成dynamic,function改成void,再改一下构造函数的调用方式(new type()改为win.New.type()),去掉javascript中的win.前缀(因为这已经是C#的方法了),就可以直接运行了。
 
  dynamic的实现是基于IDynamicObject接口和DynamicObject抽象类。而动态方法、属性的调用都被转为了GetMember、Invoke等方法的调用。

Named and optional parameter

  带有可选参数方法的声明:
 
  public StreamReader OpenTextFile(string path,Encoding encoding = null,bool detectEncoding = true,int bufferSize = 1024);
 
  命名参数必须在最后使用:
 
  OpenTextFile("foo.txt", Encoding.UTF8, bufferSize: 4096);
 
  顺序不限:
 
  OpenTextFile(bufferSize: 4096, path: "foo.txt", detectEncoding: false);

Improved COM Interoperability

  在C#中在调用COM对象如office对象时,经常需要写一堆不必要的参数:
 
  object fileName = "Test.docx";
 
  object missing = System.Reflection.Missing.Value;
 
  doc.SaveAs(ref fileName,ref missing, ref missing, ref missing,ref missing, ref missing, ref missing,ref missing, ref missing, ref missing,ref missing, ref missing, ref missing,ref missing, ref missing, ref missing);
 
  4.0中就可以直接写成:
 
  doc.SaveAs("Test.docx");

Co- and Contra-Variance

  在C#中,下面的类型转换是非法的:
 
  IList<string> strings = new List<string>();
 
  IList<object> objects = strings;
 
  因为你有可能会这样做,而编译器的静态检查无法查出错误:
 
  objects[0] = 5;
 
  string s = strings[0];
 
  4.0中在声明generic的Interface及Delegate时可以加in及out关键字,如:
 
  public interface IEnumerable<out T> : IEnumerable{IEnumerator<T> GetEnumerator();}public interface IEnumerator<out T> : IEnumerator{bool MoveNext();T Current { get; }}
 
  public interface IComparer<in T>{public int Compare(T left, T right);}
 
  out关键字的意思是说IEnumerable<T>中T只会被用在输出中,值不会被改变。这样将IEnumerable<string>转为IEnumerable<object>类型就是安全的。
 
  in的意思正好相反,是说IComparer<T>中的T只会被用在输入中,这样就可以将IComparer<object>安全的转为IComparer<string>类型。
 
  前者被称为Co-Variance, 后者就是Contra-Variance。
 
  .Net4.0中使用out/in声明的Interface:
 
  System.Collections.Generic.IEnumerable<out T>System.Collections.Generic.IEnumerator<out T>System.Linq.IQueryable<out T>System.Collections.Generic.IComparer<in T>System.Collections.Generic.IEqualityComparer<in T>System.IComparable<in T>
 
  Delegate:
 
  System.Func<in T, …, out R>System.Action<in T, …>System.Predicate<in T>System.Comparison<in T>System.EventHandler<in T>

Compiler as a Service

  4.0中增加了与编译器相关的API,这样就可以将字符串作为代码动态编译执行,跟javascript好像。
 
  Video的最后,Anders做了一个很酷的demo,大概只用了二三十行代码,就实现了在控制台中直接执行C#语句,定义并调用函数,动态创建windows form,添加button等功能,看起来完全不逊色于Python,Ruby之类语言的控制台。