在编译时解决错误的函数BUG?

时间:2013-02-21 13:47:22

标签: c# delegates

我正在使用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吗?感谢。

1 个答案:

答案 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 ...编译器正在做正确的事情。