gpt4 book ai didi

c# - 为什么在没有返回值的 lambda 中添加 throw 会被推断为 Func 而不是 Action?

转载 作者:行者123 更新时间:2023-12-03 17:20:14 26 4
gpt4 key购买 nike

这个问题在这里已经有了答案:





How can I force a throw to be a statement and not an expression (in a lambda expression)?

(4 个回答)


2年前关闭。




我遇到了一个问题,我正在编写的库的一些测试代码由于调用不明确而无法编译,但我的用法似乎很清楚。经过进一步调查,我发现添加 throw在没有返回值的 lambda 中似乎被推断为 Func<T>任何T而不是 Action正如我所料。

下面的人为示例(可以粘贴到 .NET Fiddle 中)

using System;

public class Program
{
class Foo
{

public void Method(Action action)
{
Console.WriteLine("Method A: " + action.GetType());
}

public void Method(Func<int> func)
{
Console.WriteLine("Method B: " + func.GetType());
}

/* // second call to Method becomes ambiguous if this is commented out.
public void Method(Func<bool> func)
{
Console.WriteLine(func.GetType());
}
*/

}

public static void Main()
{
var foo = new Foo();
foo.Method(() => { });
foo.Method(() => { throw new Exception("Foo!"); });
}
}

这导致
Method A: System.Action
Method B: System.Func`1[System.Int32]

也许它假设 Func<object>因为抛出它不能推断出任何返回类型......但为什么不能呢?为什么它会推断并调用具体的 Func<int> ?

此外,如果我尝试创建隐式 Func<string>像这样:
foo.Method(() => 
{
if (false)
{
throw new Exception("Foo!");
}
return "foo";
});

我得到了三个我以前没有遇到过的单独的编译错误:
Compilation error (line 38, col 16): Cannot implicitly convert type 'string' to 'int'
Compilation error (line 38, col 16): Cannot convert lambda expression to intended delegate type because some of the return types in the block are not implicitly convertible to the delegate return type
Compilation error (line 38, col 9): Anonymous function converted to a void returning delegate cannot return a value

在上面的人为示例中研究这些仍然没有多大意义,因为这些错误有点自相矛盾。如果编译器可以确定它正在返回 string并且无法转换为 int ,为什么它对不同的返回类型或返回值的 void 委托(delegate)感到不安?

谁能解释为什么编译器似乎难以理解我的意图?这是 C# 限制还是我没有看到歧义?

最佳答案

正如@Servy 在重复链接中所述

The rules for determining which overload is called are spelled out insection 7.5.3.3 of the C# specs. Specifically, when the parameter isan anonymous method, it will always prefer the overload who's delegate(or expression) has a return value over one that has no return value.This will be true whether it's a statement lambda or expressionlambda; it applies to any form of anonymous function.


在下面的代码中:
var foo = new Foo();
foo.Method(() => { });
foo.Method(() => { throw new Exception("Foo!"); });
因为 () => { throw new Exception("Foo!");}适合 ActionFunc<int> .而且,“当参数是匿名方法时,它总是更喜欢委托(delegate)(或表达式)有返回值的重载而不是没有返回值的重载”然后 Func<int>被选中。
关于其他异常(exception):
Compilation error (line 38, col 16): Cannot implicitly convert type 'string' to 'int'
Compilation error (line 38, col 16): Cannot convert lambda expression to intended delegate type because some of the return types in the block are not implicitly convertible to the delegate return type
Compilation error (line 38, col 9): Anonymous function converted to a void returning delegate cannot return a value
上述异常是因为 bad output types .在测试中,您调用了以下匿名方法,该方法返回 string但它应该返回 int因为你的 Func<int>返回 int :
foo.Method(() => 
{
if (false)
{
throw new Exception("Foo!");
}
return "foo";
});
为避免异常,您应该返回 int :
foo.Method(() => 
{
if (false)
{
throw new Exception("Foo!");
}
return 1;
});
引用
  • Overload Resolution
  • 关于c# - 为什么在没有返回值的 lambda 中添加 throw 会被推断为 Func<T> 而不是 Action?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60359145/

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