说道C#的新版本对.NET互操作的影响就不得不先说一下C#4.0的新特性。
这其中第2、3条都和互操作有关系。第2点的可选参数和命名参数并不是什么新概念了。主要在于编译器的支持。像VB.NET早就支持可选参数了。这几年C#社区对这个特性的呼声太高了,看来终于起作用了。
一、可选参数
有很多COM方法都接受可选参数。在调用此类方法时,可以根据具体需要为可选参数传递指定的值,或者忽略此参数而使用该参数的默认值。在使用托管代码调用COM方法时,根据不同的.NET语言,调用的复杂度也有所差异。由于Visual Basic .NET本身就支持可选参数(Optional关键字),它能够以可选方式使用该参数。但如果使用C#,情况就会大为不同。由于C#不支持可选参数,因此就必须为方法中的每个参数传递值,比如可以为可选参数传递System.Type.Missing以设置该参数的默认值。由于必须为所有的可选参数传递值,因此使用C#调用带有可选参数的COM方法,就不如Visual Basic .NET方便和灵活。
使用过Office PIA的朋友,在操作word文档时一定遇到过下面的例子:
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);
为了调用SaveAs方法,你不得不为填写全部不必要的参数。这就是由于老的C#版本不支持可选参数的原因。
在C#4.0出现后,情况就大不一样了。比如上面的代码可以写成:
doc.SaveAs("Test.docx");
注:《精通.NET互操作》一书特别在第6.4.7节“传递可选参数”中,介绍了如何使用Optional和DefaultParameterValue属性使得由C#构造并导出的COM方法支持可选参数。
二、对COM互操作的改进支持
新特性的第3点提到了特别针对COM互操作的改进。这包括:
1.在同一进程中host多个版本的CLR。这样可以为托管COM组建选择它所需(编译时)的运行时版本。
2. 不再必须使用PIA(Primary Interop Assembly)于COM组建交互。在过去,当你发布一个COM组建时,微软建议你随该组建发布一个PIA。这个附带的程序集PIA用来被托管应用程序客户端引用。在.NET Framework 4.0中PIA将被弱化。C#和VB编译器会判断你的程序具体使用了哪一部分COM API,并只把这部分包装成IA(互操作程序集),直接加入到你自己的应用程序集里面。
3. 重定义QueryInterface。你可以使用System.Runtime.InteropServices.ICustomQueryInterface接口自定义由托管代码实现的IUnknown::QueryInterface方法。应用程序可以用它返回特定的接口。
三、.NET Framework 4.0对线程的新特性
最后,.NET Framework 4.0在线程类Thread中加入了Yield()方法。它可以使调用线程将当前CPU的资源让给另一个准备好的线程。操作系统负责选择新线程。放弃只会对处理调用线程的CPU产生效果,操作系统不会切换执行到另一CPU,即使那个CPU正处于空闲状态。如果当前CPU上没有其他可执行的线程,Thread.Yield()方法的调用将返回false。
这个Thread.Yield()的方法相当于使用pinvoke调用Win32 API SwitchToThread。有了该新方法,就可以避免使用平台调用引入的额外开销,以及解决平台调用不能处理自定义线程行为的问题。
参考:
1. 【书】《精通.NET互操作:P/Invoke,C++ Interop和COM Interop》
2. What's New in the .NET Framework 4
3. 【视频】Managed and Native Code Interoperability: Best Practices