“x => {throw ..}”的Lambda推断为在重载方法中匹配Func ?
我不明白为什么C#最终在以下LINQPad代码中执行不正确的扩展方法:
void Main() { // Actual: Sync Action "Expected: Sync Action".Run(x => { x.Dump(); }); // Actual: Async Task "Expected: Async Task".Run(async x => { await System.Threading.Tasks.Task.Run(() => x.Dump()); }); // Actual: Async Task!! "Expected: Sync Action".Run(x => { throw new Exception("Meh"); }); } static class Extensions { public static void Run(this T instance, Action action) { "Actual: Sync Action".Dump(); action(instance); } public static void Run(this T instance, Func func) { "Actual: Async Task".Dump(); func(instance).Wait(); } }
为什么编译器认为lambda在这里返回一个Task?
我希望在第三次调用Run()时看到“Actual:Sync Action”,因为lambda中没有任何内容表明这是一个Func返回Task。
这只是一个重载解决问题。 显然,lambda x => { throw new Exception("Meh"); }
可以转换为Action
或Func
(以及与此问题无关的许多其他委托类型)。 这只是C#的重载决策规则,在这种情况下更喜欢后者。
这是一个更具代表性的例子:
void Main() { // Output: Func "Test".WhatsThis(x => { throw new Exception("Meh"); }); } static class Extensions { public static void WhatsThis(this T dummy, Action action) { "Action ".Dump(); } public static void WhatsThis (this T dummy, Func func) { "Func".Dump(); } }
至于为什么会出现这种情况,我不是百分百肯定,但随便看一下这个规格就会向我展示下面可能的解释(强调我的):
7.5.3过载分辨率
[…]
7.5.3.3从表达转换更好
给定从表达式E转换为类型T1的隐式转换C1,以及从表达式E转换为类型T2的隐式转换C2,如果以下至少一个成立,则C1是比C2更好的转换:
[…]
•E是匿名函数,T1是委托类型D1或表达式树类型
Expression
,T2是委托类型D2或表达式树类型Expression
并且以下之一成立:[…]
•D1的返回类型为Y,D2返回无效
上述就是C#学习教程:“x => {throw ..}”的Lambda推断为在重载方法中匹配Func ?分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/1013474.html