gpt4 book ai didi

c# - 带有 while (true) 的特殊重载决议

转载 作者:IT王子 更新时间:2023-10-29 04:03:51 26 4
gpt4 key购买 nike

当我遇到这种特殊情况时,我正在实现同步/异步重载:

当我有一个没有参数或返回值的常规 lambda 表达式时,它会转到带有 Action 参数的 Run 重载,这是可以预测的。但是,当该 lambda 包含 while (true) 时,它会使用 Func 参数进行重载。

public void Test()
{
Run(() => { var name = "bar"; });
Run(() => { while (true) ; });
}

void Run(Action action)
{
Console.WriteLine("action");
}

void Run(Func<Task> func) // Same behavior with Func<T> of any type.
{
Console.WriteLine("func");
}

输出:

action
func

那怎么可能呢?有什么理由吗?

最佳答案

所以首先,第一个表达式只能调用第一个重载。它不是 Func<Task> 的有效表达式,因为存在返回无效值的代码路径(void 而不是 Task)。

() => while(true) 实际上是任一签名的有效方法。 (它与 () => throw new Expression(); 等实现一起是返回任何可能类型的有效方法体,包括 void ,这是一个有趣的琐事点,以及为什么从 IDE 自动生成的方法通常只抛出异常;无论方法的签名。)无限循环的方法是其中没有不返回正确值的代码路径的方法(无论“正确值”是 voidTask 还是其他任何字面意思都是如此)。这当然是因为它从不 返回一个值,而且它以编译器可以证明的方式返回。 (如果它以编译器无法证明的方式这样做,因为它毕竟没有解决停止问题,那么我们将与 A 在同一条船上。)

因此,对于我们的无限循环,考虑到两个重载都适用,哪个更好。这将我们带到了 C# 规范的优势部分。

如果我们转到第 7.4.3.3 节的第 4 点,我们会看到:

If E is an anonymous function, T1 and T2 are delegate types or expression tree types with identical parameter lists, and an inferred return type X exists for E in the context of that parameter list (§7.4.2.11):

[...]

if T1 has a return type Y, and T2 is void returning, then C1 is the better conversion.

因此,当从匿名委托(delegate)转换时,这就是我们正在做的事情,它会更喜欢返回值的转换,而不是 void ,因此它选择 Func<Task>

关于c# - 带有 while (true) 的特殊重载决议,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24316189/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com