我正在使用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
});
}
Run Code Online (Sandbox Code Playgroud)
似乎最后一个函数调用错误地解析为Func而不是Action,它与无条件抛出异常有关.
这是一个BUG吗?谢谢.
嗯,我认为两者都是有效的候选人似乎是合理的.换句话说,我觉得() => { throw new Exception(); }将两者转换为Func<int>和Action.在这两种情况下,方法的结尾都是无法访问的 - 将它放入正常的命名方法是完全有效的,如下所示:
public int GoBang()
{
throw new Exception();
}
Run Code Online (Sandbox Code Playgroud)
然后写:
Func<int> foo = GoBang;
Run Code Online (Sandbox Code Playgroud)
因此,从转换的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 <D 1 >,T 2是委托类型D 2或表达式树类型表达式<D 2 >,其中一个以下是:
- [...]
- D 1和D 2具有相同的参数列表,并且具有以下之一:
- D 1具有返回类型Y,并且D 2返回空白.
所以这就是为什么Func<int>首选Action...编译器正在做正确的事情.