惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Attack and Defense Labs
Attack and Defense Labs
The GitHub Blog
The GitHub Blog
C
Check Point Blog
博客园_首页
MongoDB | Blog
MongoDB | Blog
N
Netflix TechBlog - Medium
F
Full Disclosure
Microsoft Security Blog
Microsoft Security Blog
爱范儿
爱范儿
Recent Announcements
Recent Announcements
阮一峰的网络日志
阮一峰的网络日志
G
GRAHAM CLULEY
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
T
Threat Research - Cisco Blogs
C
Cybersecurity and Infrastructure Security Agency CISA
V
Vulnerabilities – Threatpost
K
Kaspersky official blog
博客园 - 司徒正美
S
Schneier on Security
T
The Exploit Database - CXSecurity.com
Project Zero
Project Zero
云风的 BLOG
云风的 BLOG
Cisco Talos Blog
Cisco Talos Blog
Know Your Adversary
Know Your Adversary
雷峰网
雷峰网
V
V2EX - 技术
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Spread Privacy
Spread Privacy
罗磊的独立博客
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
S
Security Affairs
SecWiki News
SecWiki News
Schneier on Security
Schneier on Security
O
OpenAI News
Jina AI
Jina AI
PCI Perspectives
PCI Perspectives
Cyberwarzone
Cyberwarzone
Y
Y Combinator Blog
Apple Machine Learning Research
Apple Machine Learning Research
B
Blog RSS Feed
I
InfoQ
D
Docker
P
Palo Alto Networks Blog
Recorded Future
Recorded Future
M
MIT News - Artificial intelligence
博客园 - Franky
B
Blog
Scott Helme
Scott Helme
博客园 - 叶小钗
D
DataBreaches.Net

博客园 - J.D Huang

TinyDO:可能是WP首个支持中文语音识别的待办事项APP Internet TV 影音娱乐新生活 Windows Phone Developer Tools CTP 发布了! Python - 默认参数的一次性求值 Python小技巧 – True or False - J.D Huang Python小技巧 - 子串查找 - J.D Huang 新的个人博客@ http://thinkbot.info MeeGo:下一个Android? Windows Mobile 6.5.3 Developer Tool Kit 发布了 塞班(Symbian)开源了(包括Symbian 3和S60等) Windows Mobile 6.5 SDK 发布了 (2月17日更新) C#4.0新特性之(四)新的LINQ扩展方法-Zip() C#4.0新特性之(三)协变与逆变 C#4.0新特性之(一)动态查找 Android手机防盗工具DroidGuard Simple HostMonitor 实用的网管小工具 Office Mobile 2010 Beta 发布了! - J.D Huang 试了一下.Net Fx 4.0中的Parallel - J.D Huang Lambda演算与科里化(Currying)
C#4.0新特性之(二)命名参数,可选参数与COM互操作
J.D Huang · 2009-12-02 · via 博客园 - J.D Huang

 C#4.0新特性之(二)命名参数,可选参数与COM互操作

1.简介

  之前C#(2.0)和java一样是一门的纯粹的面向对象的语言,他们都使用重载而不是可选参数。但是实际上使用的其他外部程序,COM组件却经常不要求指定所有参数(这在很多VC,VB编写的组件或者操作IronPython的对象的时候很常见,他们一直使用可选参数)。这会导致一个C#程序员不得不用Type.Missing塞满整个参数列表。不过C#4.0终于支持命名参数/可选参数了。程序员可以在方法调用的时候通过命名参数指定可选参数。而这一切都是为了让.Net 4.0的动态语言运行库(DLR)在动态绑定的时候具有更好的兼容性。

2.命名与可选参数

  这个对C#来说是又一个新特征,但对C++,VB,Python etc. 的程序员来说这只是很自然的一个特征。C# 4.0种的可选参数和其他语言中的用法大致相同,这里不需要VB中额外的关键词修饰,也不能像C++中只用点点点来表示可以无视,倒是和python比较像,下面的声明是合法的:

可选参数Foo

        static void Foo(int a, String s = "i'm a string", dynamic b =null, MyClass c = null)

简单来讲,C#4.0中使用可选参数必须遵循以下几条原则:

0).可选参数必须有个编译时常量作为其默认值。如果是除String之外的引用类型(包括那个特殊的dynamic类型),默认值只能是null。下面的声明是不能通过编译的:

代码

        static void Foo(int a, String s = "i'm a string"dynamic b 

= 2, MyClass c = new

 MyClass())

1).可选参数必须从右往左出现在参数列表中(必须后出现),可选参数右边的参数(如果有的话)必须是可选参数。下面的声明是不能通过编译的:

代码

        static void Foo(String s = "i'm a string", int a, dynamic b = null, MyClass c = null)

 2).可选参数的赋值必须通过命名参数的方式指定,即必须使用可选参数的参数名称对其进行赋值。而非可选参数则不一定要用命名参数。如下的调用都是合法的:

Foo calls

            Foo(2);
            Foo(a: 
2);
            Foo(
2, s: "hello", b: 3.14);
            Foo(
2, s: "hello", b: 3.14, c:new MyClass());
            Foo(
2, c: new MyClass());

 特别的,一旦调用方法时使用的是命名参数,则命名参数的位置可以是任意顺序,如下的调用是合法的: 

代码

            Foo(b:3.14, c:new MyClass(), a:2);

唯一的影响就是上述调用中会对b先求值,然后再是c和a。函数总是按照参数出现的顺序进行求值操作的。 

  另外,可选参数不仅适用于普通的方法,还适用于构造器,索引器中,本质上它们没有什么不同。

3.可选参数与重载决策

  毫无疑问,命名参数和可选参数让CLR在方法的重载决策(overload resolution)变得稍微复杂了一些,不用担心,这里你只需要搞清楚重载决策的下面几个特点就可以了:

0).在带可选参数的方法签名中,重载决策会认可被可选参数代替的重载版本,比如下面两个声明:

       public static void Foo(int a, String s = "i'm a string", dynamic b = null, MyClass c = null);
       
public static void Foo(int a, String s = "i'm a string");

  如果按照以下方式调用,编译器会提示你它已经被上面两个方法confused了:

            Foo(2);
            Foo(a: 
2);

1).在调用方式同样合法的情况下,重载决策会优先选择不带可选参数的重载版本。比如下面两个方法:

       public static void Foo(int a, String s = "i'm a string", dynamic b = null, MyClass c = null);
       
public static void Foo(int a); 

  如果使用以下方式调用:被调用的会是void Foo(int a);这个版本:

            Foo(2);
            Foo(a: 
2);

2).在调用方式同样合法的情况下,重载决策会优先选择类型最为匹配(最易转化)的重载,例如下面两个方法:

       public static void Foo(byte a, String s = "i'm a string", dynamic b = null, MyClass c = null);
       
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填充整个参数列表了,比如Office14的Excel.ApplicatioinClass中就利用了可选参数定义了一个intersect方法:

代码

public virtual Range Intersect(Range Arg1, Range Arg2, object Arg3 = Type.Missing, object Arg4 = Type.Missing, object Arg5 = Type.Missing, object Arg6 = Type.Missing, object Arg7 = Type.Missing, object Arg8 = Type.Missing, object Arg9 = Type.Missing, object Arg10 = Type.Missing, object Arg11 = Type.Missing, object Arg12 = Type.Missing, object Arg13 = Type.Missing, object Arg14 = Type.Missing, object Arg15 = Type.Missing, object Arg16 = Type.Missing, object Arg17 = Type.Missing, object Arg18 = Type.Missing, object Arg19 = Type.Missing, object Arg20 = Type.Missing, object Arg21 = Type.Missing, object Arg22 = Type.Missing, object Arg23 = Type.Missing, object Arg24 = Type.Missing, object Arg25 = Type.Missing, object Arg26 = Type.Missing, object Arg27 = Type.Missing, object Arg28 = Type.Missing, object Arg29 = Type.Missing, object Arg30 = Type.Missing);

 换做以前要手动指定这三十个参数的确是一件抓狂的事情。

      在性能方面,由于C#4种编译器可以把PIAs按需部分编译到你的程序集中,不必每次都完全load这组庞大的互操作程序集,这对提高COM交互性能很有帮助。另外还有一个语法糖就是在COM调用的时候可以不使用ref传递参数,这避免了程序员自行创建临时变量来hold这些参数,不过这里不使用ref并不代表不按引用传递而按值传递,实际上C#编译器会自行帮你创建临时变量并任然按引用把参数传递给调用者。

5.总结

     C#4.0中很大一部分特征弥补了它之前的一些令开发者不爽的地方,无论是动态类型还是可选参数,新的C#让那些和各种组件(COM,IronPython etc.)打交道的程序员获得一定程度的解脱。C#越来越变得以人为本,更确切地,以程序员为本。

Author: Freesc Huang @ CNBlogs