Jb *_*ain 18 c# compiler-construction csc c#-4.0
C#4,为简化COM互操作,允许调用者在COM接口中省略ref参数前面的ref关键字.
我很惊讶今天看到这也适用于扩展COM接口的扩展方法.请参阅以下内容,编译代码:
using System;
using System.Runtime.InteropServices;
[ComImport, Guid ("cb4ac859-0589-483e-934d-b27845d5fe74")]
interface IFoo {
}
static class Program {
public static void Bar (this IFoo self, ref Guid id)
{
id = Guid.NewGuid ();
}
static void Main ()
{
Foo (null);
}
static void Foo (IFoo o)
{
Guid g = Guid.NewGuid ();
Console.WriteLine (g);
// note that g is passed as is, and not as ref g
o.Bar (g);
Console.WriteLine (g);
}
}
Run Code Online (Sandbox Code Playgroud)
我没有在规范中找到任何解释这种行为的内容.
我的感觉是COM接口之外的代码,即使它是扩展COM接口的扩展方法,也应该遵循常规的C#规则,并强制使用ref关键字.因此我在连接上提交了一个错误.并不是说我认为这将被修复,即使它被认为是一个bug,已经有代码依赖于此.
错误?不是一个bug?
我不认为这是一个错误;正如你所说,它看起来更像是“COM voodoo”。在幕后,C# 编译器会发出实际上正确的内容,如下所示:
private static void Foo(IFoo o)
{
...
Guid g = Guid.NewGuid();
Guid <>r__ComRefCallLocal0 = g;
Bar(o, ref <>r__ComRefCallLocal0);
...
}
Run Code Online (Sandbox Code Playgroud)
C# 实际上充满了技巧。如果您向 IFoo 添加一个方法,例如这样,
[ComImport, Guid("cb4ac859-0589-483e-934d-b27845d5fe74")]
interface IFoo
{
void Test([Optional] ref object test);
}
Run Code Online (Sandbox Code Playgroud)
同样,您将能够在 C# 4 中声明这一点:
static void Foo(IFoo o)
{
Guid g = Guid.NewGuid();
o.Test(g);
}
Run Code Online (Sandbox Code Playgroud)
当然,这一切之所以有效,是因为 CSC.EXE 对 ComImport 属性有深入的了解。这些新的神奇互操作技巧被添加到 C# 4.0 中,以便能够轻松地与现有 COM 接口进行互操作。好吧,主要是针对 Microsoft Office 界面和方法,尤其是可怕的“引用丢失”参数大军:-)
我认为这在任何地方都没有完全指定。这就是 C# 4 规范的全部内容:
17.5 互操作属性 注意:本节仅适用于 C# 的 Microsoft .NET 实现。17.5.1 与 COM 和 Win32 组件的互操作 .NET 运行时提供了大量属性,使 C# 程序能够与使用 COM 和 Win32 DLL 编写的组件进行互操作。例如,DllImport 属性可以用在静态 extern 方法上,以指示要在 Win32 DLL 中找到该方法的实现。这些属性可在 System.Runtime.InteropServices 命名空间中找到,这些属性的详细文档可在 .NET 运行时文档中找到。
以下是 MSDN 上的一些页面:
| 归档时间: |
|
| 查看次数: |
389 次 |
| 最近记录: |