C# NET中的代理:它们是如何构造的?
在检查C#和.NET中的代表时,我注意到一些有趣的事实: 在C#中创建委托会创建一个派生自C# NET中的代理:它们是如何构造的?,c#,.net,delegates,clr,.net-internals,C#,.net,Delegates,Clr,.net Internals,在检查C#和.NET中的代表时,我注意到一些有趣的事实: 在C#中创建委托会创建一个派生自MulticastDelegate并带有构造函数的类: 这意味着它需要实例和指向方法的指针。然而,在C#中构造委托的语法表明它有一个构造函数 我可以将int()识别为函数实例(int*target()将是C++中的函数指针)。显然,C#编译器从函数名定义的方法组中选择正确的方法并构造委托。因此,第一个问题是,C#编译器(确切地说是Visual Studio)从何处选择此构造函数签名?我没有注意到任何特殊的属
MulticastDelegate
并带有构造函数的类:
这意味着它需要实例和指向方法的指针。然而,在C#中构造委托的语法表明它有一个构造函数
我可以将int()
识别为函数实例(int*target()
将是C++中的函数指针)。显然,C#编译器从函数名定义的方法组中选择正确的方法并构造委托。因此,第一个问题是,C#编译器(确切地说是Visual Studio)从何处选择此构造函数签名?我没有注意到任何特殊的属性或会有区别的东西。这是某种编译器/visualstudio魔法吗?如果不是,则T(args)目标
构造是否在C#中有效?我没有设法用它编译任何东西,例如:
int()target=MyMethod
是无效的,使用MyMetod
执行任何操作都是无效的,例如对其调用.ToString()
(这确实有一定意义,因为从技术上讲,这是一个方法组,但我认为应该可以通过强制转换显式地选择一个方法,例如(int())MyFunction
。那么,所有这些都是纯粹的编译器魔法吗?通过reflector查看构造可以揭示另一种语法:
Func CS$1$0000=新Func(null,(IntPtr)Foo)
这与反汇编的构造函数签名是一致的,但这不会编译
最后一个有趣的注意事项是类Delegate
和多播Delegate
还有另一组构造函数:
.method族隐藏特殊名称rtspecialname实例
void.ctor(类系统类型目标,字符串“方法”)cil管理
从实例和方法指针到类型和字符串方法名称的转换发生在何处?这是否可以用自定义委托构造函数签名中的运行时管理的关键字来解释,即运行时是否在此处执行其工作
编辑:好吧,我想我应该重新表述一下我想通过这个问题说的内容。基本上,我建议在委托构造中不仅要用到C#编译器/CLR魔术,还要用到一些Visual Studio魔术,因为Intellisense在建议构造函数参数时会抛出一些新语法,甚至隐藏一个of它们(例如,反射器不使用此语法和构造函数)
我想知道这个断言是否正确,函数实例语法在C#中是否有更深的含义,或者它只是Visual Studio magic部分为清晰起见实现的某种常量格式(这很有意义,因为它看起来像无效的C#)简言之,如果我正在实施Intellisense,我应该为代表们施展魔法,还是可以通过一些聪明的机制来构建建议
最终编辑:因此,流行的共识是这确实是VS magic。看到其他此类VS行为的示例(请参阅Marc Gravell的评论)让我确信情况确实如此。您首先定义委托(Visual Studio就是这样知道目标方法的签名的):
然后,您可以像这样构造委托实例:
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#自动选择与委托签名匹配的方法
编辑:当VisualStudio的Intellisense向您显示int()时target
建议,它向您显示了可以使用的C#方法的签名。C#编译器将C#表示转换为IL。IL实现看起来会有所不同,因为IL不是C风格的语言,C#编译器提供语法糖来抽象出实现细节。第一个参数是resolv从对象引用中删除(对于静态方法,或null
),没有魔力
但是,Re是第二个参数-它是一个非托管指针(原生int);简而言之,没有其他直接C#语法可以使用此构造函数-它使用特定的IL指令()从元数据解析函数。但是,您可以使用通过反射创建委托。您也可以使用IL emit(DynamicMethod
等),但这并不有趣。这只是一个猜测,所以如果我错了,请不要开枪打我,但我认为Intellisense正在从委托上定义的Invoke
方法中获取目标方法的签名。Reflector清楚地显示系统上的Invoke
方法。操作
是:
[MethodImpl(0, MethodCodeType=MethodCodeType.Runtime)]
public virtual void Invoke(T obj);
这与Intellisense提供的签名建议相同。神奇之处在于,Intellisense在发现委托类型时,会查看Invoke
方法,并建议一个构造函数,该构造函数采用与之匹配的目标。我想他的意思是从低级角度来看。@Saulius:theint()目标本身不是有效的C#,但它们如何在Intellisense中表示目标?。这就是问题所在-它们必须显示一些东西,所以它们只是为了清晰起见显示一些虚构的语法(仅用于代表的visual studio magic),还是说它具有更深层的含义?:)@Saulius:为了清晰起见,我假设这只是一个虚构的语法。好吧,所以方法指针不受C#支持,但“函数实例”在哪里-像语法是从哪里来的?我理解从双参数构造函数到单参数c-tor是编译器的魔法,但是visual studio从何处获得建议单参数构造函数的想法(我在其他任何地方都找不到它)?@Saulius-因为这是语言规范所要求的;它没有讨论构造函数,但它声明语法是(例如)neweventhandler(someObject.SomeMethod);
-即使compi
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);
[MethodImpl(0, MethodCodeType=MethodCodeType.Runtime)]
public virtual void Invoke(T obj);