c# - "x => { throw .. }"的 Lambda 推断匹配重载方法中的 Func<T,Task>?

标签 c# .net lambda overloading type-inference

我不明白为什么 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();
    }
}

为什么编译器认为 lambda 在这里返回了一个 Task?

我希望在第三次调用 Run() 时看到“Actual: Sync Action”,因为 lambda 中没有任何内容表明这是一个 Func 返回任务。

最佳答案

这只是一个重载解析问题。显然,lambda x => { throw new Exception("Meh"); }可以转换为 Action<T>Func<T, SomeNonVoidType> (以及与此问题无关的许多其他委托(delegate)类型)。在这种情况下,只是 C# 的重载解析规则更喜欢后者。

这里有一个更有代表性的例子:

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();
    }
}

至于为什么会这样,我不是百分百确定,但随便看看spec向我展示以下可能的解释(强调我的):

7.5.3 Overload resolution

[...]

7.5.3.3 Better conversion from expression

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 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:

[...]

• D1 has a return type Y, and D2 is void returning

关于c# - "x => { throw .. }"的 Lambda 推断匹配重载方法中的 Func<T,Task>?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23486452/

相关文章:

c# - 在 LINQ 表达式异常中检测到循环

c# - 停止调试时的执行方法

c# - 在 Unity 中将 Vector3 转换为 float

lambda - Rust 中 lambda 表达式的生命周期

android retrolambda,语句lambda可以替换为表达式lambda

c# - Entity Framework 模型的两个引用冲突

.net - 向同一解决方案中的多个项目添加相同的 "*.dll"引用

c# - 使用 ToObject 方法反序列化 Json 会产生默认属性值

.net - SynchronizationContext.Post的处理顺序

C# 列表,从对象列表创建列表对象