3.可选参数与重载决策
毫无疑问,命名参数和可选参数让CLR在方法的重载决策(overload resolution)变得稍微复杂了一些,不用担心,这里你只需要搞清楚重载决策的下面几个特点就可以了:
(1).在带可选参数的方法签名中,重载决策不会认可被可选参数代替的重载版本,比如下面两个声明:
public static void Foo(int a, String s = "i'm a string");
如果按照以下方式调用,编译器会提示你它已经被上面两个方法confused了:
Foo(a: 2);
(2).在调用方式同样合法的情况下,重载决策会优先选择不带可选参数的重载版本。比如下面两个方法:
public static void Foo(int a);
如果使用以下方式调用:被调用的会是void Foo(int a);这个版本:
Foo(a: 2);
(3).在调用方式同样合法的情况下,重载决策会优先选择类型最为匹配(最易转化)的重载,例如下面两个方法:
public static void Foo(object a);
Foo(2)和Foo(a:2)都将调用前一个方法,因为int到byte是值类型之间的转化,其代价要比从int转到object的代价低。
4.C#4.0中的COM互操作
在上一篇文章中提到的动态类型绑定和本文前面提到的命名参数,可选参数都为CLR的COM互操作提供了便利。有了动态类型,访问COM对象时不必再对返回的COM对象进行显式的类型转换了,因为返回的是一个dynamic类型的对象,我们可以直接在它上面调用方法/属性/索引器等,例如excelApp.Cells[row,column].Value = "some value"; 这里的Cells[row,column]返回的是一个dynamic类型的对象,而之前都是返回的object需要显式转换才能操作它,比如:((Excel.Range)excelApp.Cells[row,column]).Value = "some value";
而有了可选参数,广大程序员们也不必再猛力用Type.Missing填充整个参数列表了,比如Office12的Excel.ApplicatioinClass中就利用了可选参数定义了一个intersect方法:
换做以前要手动指定这三十个参数的确是一件抓狂的事情。
在性能方面,由于C#4种编译器可以把PIAs按需部分编译到你的程序集中,不必每次都完全load这组庞大的互操作程序集,这对提高COM交互性能很有帮助。另外还有一个语法糖就是在COM调用的时候可以不使用ref传递参数,这避免了程序员自行创建临时变量来hold这些参数,不过这里不使用ref并不代表不按引用传递而按值传递,实际上C#编译器会自行帮你创建临时变量并任然按引用把参数传递给调用者。
5.总结
C#4.0中很大一部分特征弥补了它之前的一些令开发者不爽的地方,无论是动态类型还是可选参数,新的C#让那些和各种组件(COM,IronPython etc.)打交道的程序员获得一定程度的解脱。C#越来越变得以人为本,更确切地,以程序员为本。