5

Visual Studio 2012Update1と.NET4.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
    });
}

最後の関数呼び出しがActionではなくFuncに誤って解決されているようで、無条件に例外をスローすることに関係しています。

これはバグですか?ありがとう。

4

1 に答える 1

7

まあ、両方が有効な候補であると私には合理的に思えます。() => { throw new Exception(); }つまり、との両方Func<int>に変換しても問題ないと思いますAction。どちらの場合も、メソッドの終わりに到達できません。これを次のような通常の名前付きメソッドに入れることは完全に有効です。

public int GoBang()
{
    throw new Exception();
}

そして、次のように書きます。

Func<int> foo = GoBang;

したがって、ラムダ式から両方への変換Func<int>Action有効です。次に、使用する方法を選択する必要があります。これは、仕様セクション7.5.3.2(より優れた関数メンバー)で指定されています。これには、次のものが含まれます。

少なくとも1つの引数については、ExからPxへの変換は、ExからQx変換よりも優れています

この時点で、セクション7.5.3.3(式からのより良い変換)が始まります:

次の少なくとも1つが当てはまる場合、C1はC2より優れた変換です。

  • [...]
  • E is an anonymous function, T1 is either a delegate type D1 or an expression tree type Expression<D1>, T2 is either a delegate type D2 or an expression tree type Expression<D2>, and one of the following holds:

    • [...]
    • D1 and D2 have identical parameter lists, and one of the following holds:
    • D1 has a return type Y, and D2 is void returning.

So that's why Func<int> is preferred over Action... the compiler's doing the right thing.

于 2013-02-21T13:51:12.610 に答える