我正在使用Visual Studio 2012 Update 1,这里是.NET 4.5代码。
void Test(Action a) { }
void Test(Func<int> a) { }
void TestError()
{
bool throwException = true;
//Resolves to Test(Action a)
Test(() =>
{
});
//Resolves to Test(Action a)
Test(() =>
{
if (throwException) throw new Exception();
});
//Resolves to Test(Func<int> a)
//(This seems like a bug since there is no return value)
Test(() =>
{
throw new Exception();
});
//Resolves to Test(Action a)
//(With warning unreachable code detected)
Test(() =>
{
throw new Exception();
return; //unreachable code detected
});
}
似乎最后一个函数调用错误地解析为Func而不是Action,它与无条件抛出异常有关。
这是一个BUG吗?感谢。
答案 0 :(得分:7)
嗯,我认为两者都是有效候选人似乎是合理的。换句话说,我认为将() => { throw new Exception(); }
转换为Func<int>
和Action
都没关系。在这两种情况下,方法的结尾都是无法访问的 - 将它放入一个正常的命名方法是完全有效的:
public int GoBang()
{
throw new Exception();
}
然后写:
Func<int> foo = GoBang;
因此,从lambda表达式到Func<int>
和Action
的转换都是有效的。我们现在需要选择使用哪种方法。这在规范7.5.3.2节(更好的函数成员)中指定,其中包括:
对于至少一个参数,从E x 到P x 的转换优于从E x 到Q <的转换子> X 子>
此时,第7.5.3.3节(从表达式转换得更好)开始了:
C 1 是一个更好的转换而不是C 2 如果至少有下列之一:
- [...]
E是一个匿名函数,T 1 是委托类型D 1 或表达式树类型Expression&lt; D 1 &gt;,T 2 是委托类型D 2 或表达式树类型表达式&lt; D 2 &gt;,其中一个以下是:
- [...]
- D 1 且D 2 具有相同的参数列表,并且其中一个成立:
- D 1 的返回类型为Y,D 2 无效返回。
这就是为什么Func<int>
优先于Action
...编译器正在做正确的事情。