简体   繁体   English

“x =&gt; {throw ..}”的Lambda推断为匹配Func <T,Task> 在重载方法?

[英]Lambda of “x => { throw .. }” inferred to match Func<T,Task> in overloaded method?

I don't understand why C# ends up executing an incorrect extension method in the following LINQPad code: 我不明白为什么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<T>(this T instance, Action<T> action)
    {
        "Actual: Sync Action".Dump();
        action(instance);
    }

    public static void Run<T>(this T instance, Func<T, System.Threading.Tasks.Task> func)
    {
        "Actual: Async Task".Dump();
        func(instance).Wait();
    }
}

Why does the compiler think that the lambda returns a Task here? 为什么编译器认为lambda在这里返回一个Task?

I expected to see "Actual: Sync Action" in the third call to Run() since nothing in the lambda indicates that this is a Func returning Task. 我希望在第三次调用Run()时看到“Actual:Sync Action”,因为lambda中没有任何内容表明这是一个Func返回Task。

This is simply an overload resolution issue. 这只是一个重载解决问题。 Clearly, the lambda x => { throw new Exception("Meh"); } 显然,lambda x => { throw new Exception("Meh"); } x => { throw new Exception("Meh"); } can be converted to either an Action<T> or to a Func<T, SomeNonVoidType> (as well as to many other delegate types irrelevant to this question). x => { throw new Exception("Meh"); }可以被转化到任何一个Action<T>或一个Func<T, SomeNonVoidType>以及许多其他委托类型无关这个问题)。 It's simply C#'s overload resolution rules that prefer the latter in this case. 这只是C#的重载决策规则,在这种情况下更喜欢后者。

Here's a more representative example: 这是一个更具代表性的例子:

void Main()
{
    // Output: Func<T, int>
    "Test".WhatsThis(x => { throw new Exception("Meh"); });
}

static class Extensions
{
    public static void WhatsThis<T>(this T dummy, Action<T> action)
    {
       "Action<T>".Dump();
    }
    public static void WhatsThis<T>(this T dummy, Func<T, int> func)
    {
       "Func<T, int>".Dump();
    }
}

As for why this is the case, I'm not 100% sure, but a casual look at the spec shows me the below likely explanation (emphasis mine): 至于为什么会出现这种情况,我不是百分百肯定,但随便看一下这个规格就会向我展示下面可能的解释(强调我的):

7.5.3 Overload resolution 7.5.3过载分辨率

[...] [...]

7.5.3.3 Better conversion from expression 7.5.3.3更好地从表达转换

Given an implicit conversion C1 that converts from an expression E to a type T1, and an implicit conversion C2 that converts from an expression E to a type T2, C1 is a better conversion than C2 if at least one of the following holds: 给定从表达式E转换为类型T1的隐式转换C1,以及从表达式E转换为类型T2的隐式转换C2,如果以下至少一个成立,则C1是比C2更好的转换:

[...] [...]

• E is an anonymous function, T1 is either a delegate type D1 or an expression tree type Expression<D1> , T2 is either a delegate type D2 or an expression tree type Expression<D2> and one of the following holds: •E是匿名函数,T1是委托类型D1或表达式树类型Expression<D1> ,T2是委托类型D2或表达式树类型Expression<D2>并且以下之一成立:

[...] [...]

• D1 has a return type Y, and D2 is void returning •D1的返回类型为Y,D2返回无效

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 仅当S和T不同时,才从λ表达式的输出推断出Func <S,T>的T? - T of Func<S, T> is inferred from output of lambda expression only when S and T are different? 将其传递给需要 Func 的函数时是否需要异步 lambda <Task<T> &gt;? - Is async lambda needed when passing it to a function that expects Func<Task<T>>? 方法 MyFunction 的类型参数<T> (功能<T> ) 不能从用法推断 - The type arguments for method MyFunction<T>(Func<T>) cannot be inferred from the usage FUNC <T, TResult> parameter-无法从用法中推断出方法的类型参数 - Func<T, TResult> parameter - The type arguments for method cannot be inferred from the usage 这是重载的任务方法吗? - Is this Overloaded TASK Method? 将 lambda 异步到表达式<Func<Task> &gt; - Async lambda to Expression<Func<Task>> 传递`Func <Task> `to a method - 调用func与lambda和async / await lambda之间的任何差异? - Passing `Func<Task>` to a method - any differences between calling func vs. lambda vs. async/await lambda? 是Func的同步void方法 <Task> 或Func <Task<T> &gt;论点实际上有用吗? - Is a synchronous void method with Func<Task> or Func<Task<T>> arguments practically useful? 如何调用需要Func的方法 <T> 带有lambda表达式参数 - How to call a method that needs a Func<T> with an lambda Expression argument 任务<t>和 Func 委托中的任务</t> - Task<T> and Task in Func delegate
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM