c# - .NET 中的委托(delegate) : how are they constructed?

标签 c# .net delegates clr .net-internals

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

在 C# 中创建委托(delegate)会创建一个派生自 MulticastDelegate 的类,并带有构造函数:

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

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

new MyDelegate(int () target)

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

int () target = MyMethod;

无效,因此对 MyMetod 做任何事情也是如此,例如在其上调用 .ToString()(嗯,这确实有一定道理,因为从技术上讲,这是一个方法 group,但我想应该可以明确地挑选出一个方法通过强制转换,例如 (int())MyFunction。那么所有这些纯粹的编译器魔术是什么?通过反射器查看构造揭示了另一种语法:

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

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

最后一个有趣的注意事项是 DelegateMulticastDelegate 类还有另一组构造函数:

.method family hidebysig specialname rtspecialname instance void .ctor(class System.Type target, string 'method') cil managed

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

编辑:好的,所以我想我应该重新表述我想通过这个问题表达的意思。基本上,我建议在委托(delegate)构造中不仅涉及 C# 编译器/CLR 魔法,而且还有一些 Visual Studio 魔法,因为 Intellisense 在建议构造函数参数时会翻转一些新语法,甚至隐藏其中一个它们(例如,Reflector 不使用这种语法和构造函数)。

我想知道这个断言是否正确,以及函数实例语法在 C# 中是否有更深层次的含义,或者它只是 Visual Studio 魔术部分为了清晰起见而实现的一些常量格式(这是有道理的,因为它看起来无效C#) ?简而言之,如果我正在实现 Intellisense,我应该为委托(delegate)做一些魔术,还是可以通过一些聪明的机制来构建建议?

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

最佳答案

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

关于第二个 参数,但是 - 它是一个非托管指针( native int);简而言之,没有其他直接 C# 语法可以使用此构造函数 - 它使用特定的 IL 指令 (ldftn) 从元数据解析函数。但是,您可以使用 Delegate.CreateDelegate通过反射创建委托(delegate)。您也可以使用 IL emit(DynamicMethod 等),但这并不好玩。

关于c# - .NET 中的委托(delegate) : how are they constructed?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2443757/

相关文章:

c# - 如何在 specflow 特征表中使用 "|"关键字

.net - MVVM - 如何在运行时为 xamdatagrid 创建列?

c# - 使用动态注入(inject)类创建委托(delegate)

c# - 在文本框中获取前 10 行和后 10 行 C#

C# 区域设置混淆

c# - 如何正确包装 Dictionary<T,U> 并公开枚举器?

.net - 除了 Microsoft 和 Mono 之外,还有其他 .Net 实现吗?

ios - 将选定的行复制到一个数组,该数组填充 Xcode 中的另一个 UITableView

python - 将整个函数作为字符串获取/并将字符串转换为函数?

c# - Linq:按年月分组,管理空月