在检查 C# 和 .NET 中的委托时,我注意到一些有趣的事实:

在 C# 中创建委托会创建一个派生类 MulticastDelegate 使用构造函数:

.method public hidebysig specialname rtspecialname instance 
   void .ctor(object 'object', native int 'method') runtime managed { }

这意味着它需要实例和指向方法的指针。然而,在 C# 中构造委托的语法表明它有一个构造函数

new MyDelegate(int () target)

我能认出的地方 int () 作为函数实例(int *target() 在 C++ 中将是一个函数指针)。显然,C# 编译器从函数名定义的方法组中挑选出正确的方法并构造委托。所以第一个问题是,C# 编译器(或者准确地说是 Visual Studio)从哪里选择这个构造函数签名?我没有注意到任何特殊属性或会产生区别的东西。这是某种编译器/视觉工作室魔法吗?如果不是的话,是 T (args) target 构造在 C# 中有效吗?我没有设法用它来编译任何东西,例如:

int () 目标 = MyMethod;

是无效的,所以做任何事情都是无效的 MyMetod, ,例如呼叫 .ToString() 就它而言(这确实有一定道理,因为这在技术上是一种方法 团体, ,但我想应该可以通过强制转换来显式地选择一个方法,例如 (int())MyFunction. 。那么这一切纯粹是编译器的魔法吗?通过反射器查看构造揭示了另一种语法:

Func CS$1$0000 = new Func(null, (IntPtr) Foo);

这与反汇编的构造函数签名一致,但无法编译!

最后一个有趣的说明是,这些课程 DelegateMulticastDelegate 还有另一组构造函数:

从实例和方法指针到类型和字符串方法名称的转换发生在哪里?这可以解释为 runtime managed 自定义委托构造函数签名中的关键字,即运行时在这里做它的工作吗?

编辑:好的,所以我想我应该通过这个问题重新表述我想说的内容。基本上我建议委托构造中不仅涉及 C# 编译器/CLR 魔法,还涉及一些 视觉工作室 神奇的是,因为智能感知在建议构造函数参数时会弹出一些新语法,甚至隐藏其中之一(例如Reflector 不使用此语法和构造函数)。

我想知道这个断言是否正确,以及函数实例语法在 C# 中是否有更深层的含义,或者只是 Visual Studio 魔术部分为了清晰起见而实现的某种常量格式(这是有道理的,因为它看起来像无效的 C#)?简而言之,如果我正在实现智能感知,我应该为代表们施展一些魔法,还是可以通过某种巧妙的机制构建建议?

最终编辑:所以,普遍的共识是,这确实是VS魔法。看到此类 VS 行为的其他示例(请参阅 Marc Gravell 的评论)让我相信情况确实如此。

有帮助吗?

解决方案

第一个参数是从对象引用解析的(或 null 对于静态方法);那里没有魔法。

重新 第二 然而,参数 - 它是一个非托管指针(本机 int);简而言之,别无选择 直接的 可以使用此构造函数的 C# 语法 - 它使用特定的 IL 指令 (ldftn) 从元数据解析函数。但是,您可以使用 Delegate.CreateDelegate 通过反射创建委托。您还可以使用 IL 发出(DynamicMethod 等),但这并不有趣。

其他提示

首先定义委托(这就是 Visual Studio 了解目标方法签名的方式):

delegate void MyDelegate();

然后您可以像这样构造委托实例:

MyDelegate method = new MyDelegate({method name});

// If this was the method you wanted to invoke:
void MethodToInvoke()
{
    // do something
}

MyDelegate method = new MyDelegate(MethodToInvoke);

C# 自动选择与委托签名匹配的方法。

编辑:当 Visual Studio 的 Intellisense 向您显示 int () target 建议,它向您展示了您可以使用的 C# 方法的签名。C# 编译器将 C# 表示形式转换为 IL。IL 实现看起来会有所不同,因为 IL 不是 C 风格语言,并且 C# 编译器提供语法糖来抽象实现细节。

这只是一个猜测,所以如果我错了,请不要开枪打我,但我认为 Intellisense 正在从 Invoke 委托上定义的方法。反射镜清楚地表明 Invoke 方法上 System.Action<T> 是:

[MethodImpl(0, MethodCodeType=MethodCodeType.Runtime)]
public virtual void Invoke(T obj);

这与Intellisense提供的签名建议相同。神奇的是智能感知,当发现委托类型时,会查看 Invoke 方法并建议一个采用与其匹配的目标的构造函数。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top