C#编译器奇怪与委托构造函数
基于以下问题 ,我发现了c#编译器的一些奇怪行为。
以下是有效的C#:
static void K() {} static void Main() { var k = new Action(new Action(new Action(K)))); }
我发现奇怪的是编译器’解构’传递的委托。
ILSpy输出如下:
new Action(new Action(new Action(null, ldftn(K)), ldftn(Invoke)).Invoke);
可以看出,它会自动决定使用委托的Invoke
方法。 但为什么?
实际上,代码不清楚。 我们是否有一个三重包装的委托(实际)或内部委托只是’复制’到外部委托(我最初的想法)。
当然,如果意图就像编译器发出代码一样,那么应该写一下:
var k = new Action(new Action(new Action(K).Invoke).Invoke);
与反编译代码类似。
任何人都可以certificate这种“令人惊讶的”转变的原因吗?
更新:
我只能想到一个可能的用例; 委托类型转换。 例如:
delegate void Baz(); delegate void Bar(); ... var k = new Baz(new Bar( new Action (K)));
如果使用相同的委托类型,编译器可能会发出警告。
规范(第7.6.10.5节)说:
现在假设编译器将其转换为类似于您的建议:
new Action( a.Target, a.Method)
这只会创建一个具有单个方法调用的调用列表的委托。 对于多播代表,它会违反规范。
示例代码:
using System; class Program { static void Main(string[] args) { Action first = () => Console.WriteLine("First"); Action second = () => Console.WriteLine("Second"); Action both = first + second; Action wrapped1 = (Action) Delegate.CreateDelegate(typeof(Action), both.Target, both.Method); Action wrapped2 = new Action(both); Console.WriteLine("Calling wrapped1:"); wrapped1(); Console.WriteLine("Calling wrapped2:"); wrapped2(); } }
输出:
Calling wrapped1: Second Calling wrapped2: First Second
如您所见,编译器的实际行为与规范匹配 – 您建议的行为不符合规范。
这部分是由于Delegate
有点奇怪的“有时单演,有时多演员”的性质,当然……
当您尝试将委托视为方法时,编译器实际上使用委托的Invoke()
方法。 因此,例如,下面的两行编译为完全相同的IL(都调用Invoke()
):
k(); k.Invoke();
我认为你所看到的奇怪之处就是这样的结果。 委托构造函数需要一个方法(或者更确切地说,一个方法组),但它会获得一个委托。 因此它将其视为一种方法并使用Invoke()
方法。
至于含义,它是调用委托调用实际方法的委托。 您可以通过访问委托的Method
和Target
属性来自行validation。 在最外层委托的情况下, Method
是Action.Invoke
和Target
内部委托。
摘要
var action = new Action(K) => Action action = new Action(null, ldftn(K)) new Action(action) => new Action(action, ldftn(Action.Invoke))
我希望这可以解释发生了什么?
上述就是C#学习教程:C#编译器奇怪与委托构造函数分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/1001731.html