99

次のコードでは、割り当てられていないローカル変数 "numberOfGroups" が使用されます。

int numberOfGroups;
if(options.NumberOfGroups == null || !int.TryParse(options.NumberOfGroups, out numberOfGroups))
{
    numberOfGroups = 10;
}

ただし、このコードは正常に動作します (ただし、ReSharper= 10は冗長であると述べています)。

int numberOfGroups = 10;
if(options.NumberOfGroups == null || !int.TryParse(options.NumberOfGroups, out numberOfGroups))
{
    numberOfGroups = 10;
}

||何か足りないのですか、それともコンパイラが私の.

dynamicこれを問題の原因に絞り込みました(options上記のコードでは動的変数でした)。なぜ私はこれを行うことができないのですか?

このコードはコンパイルされません:

internal class Program
{
    #region Static Methods

    private static void Main(string[] args)
    {
        dynamic myString = args[0];

        int myInt;
        if(myString == null || !int.TryParse(myString, out myInt))
        {
            myInt = 10;
        }

        Console.WriteLine(myInt);
    }

    #endregion
}

ただし、このコード次のことを行います。

internal class Program
{
    #region Static Methods

    private static void Main(string[] args)
    {
        var myString = args[0]; // var would be string

        int myInt;
        if(myString == null || !int.TryParse(myString, out myInt))
        {
            myInt = 10;
        }

        Console.WriteLine(myInt);
    }

    #endregion
}

dynamicこれが要因になるとは思いもしませんでした。

4

3 に答える 3

73

これはコンパイラのバグだと確信しています。いい発見!

編集: Quartermeister が示すように、これはバグではありません。dynamic は、初期化されない原因となる奇妙なtrue演算子を実装する可能性yがあります。

最小限の再現は次のとおりです。

class Program
{
    static bool M(out int x) 
    { 
        x = 123; 
        return true; 
    }
    static int N(dynamic d)
    {
        int y;
        if(d || M(out y))
            y = 10;
        return y; 
    }
}

それが違法である理由がわかりません。dynamic を bool に置き換えると、問題なくコンパイルされます。

明日は実際に C# チームと会う予定です。私は彼らにそれを言及します。エラーをお詫びします。

于 2013-04-30T17:37:44.647 に答える
52

動的式の値が、オーバーロードされたtrueoperatorを持つ型である場合、変数が割り当てられていない可能性があります。

演算子は||演算子を呼び出してtrue右側を評価するかどうかを決定し、次にifステートメントはtrue演算子を呼び出して本体を評価するかどうかを決定します。通常の の場合bool、これらは常に同じ結果を返すため、正確に 1 つが評価されますが、ユーザー定義の演算子の場合、そのような保証はありません!

Eric Lippert の repro に基づいて作成した短い完全なプログラムは、どちらのパスも実行されず、変数が初期値を持つ場合を示しています。

using System;

class Program
{
    static bool M(out int x)
    {
        x = 123;
        return true;
    }

    static int N(dynamic d)
    {
        int y = 3;
        if (d || M(out y))
            y = 10;
        return y;
    }

    static void Main(string[] args)
    {
        var result = N(new EvilBool());
        // Prints 3!
        Console.WriteLine(result);
    }
}

class EvilBool
{
    private bool value;

    public static bool operator true(EvilBool b)
    {
        // Return true the first time this is called
        // and false the second time
        b.value = !b.value;
        return b.value;
    }

    public static bool operator false(EvilBool b)
    {
        throw new NotImplementedException();
    }
}
于 2013-04-30T19:08:42.627 に答える
7

MSDN から(強調鉱山):

動的な型により、コンパイル時の型チェックをバイパスする操作が可能になります。代わりに、これらの操作は実行時に解決されます。dynamic 型は、Office Automation API などの COM API、IronPython ライブラリなどの動的 API、および HTML ドキュメント オブジェクト モデル (DOM) へのアクセスを簡素化します。

ダイナミック型は、ほとんどの状況でオブジェクト型のように動作します。ただし、dynamic 型の式を含む操作は、コンパイラによって解決または型チェックされません。

コンパイラは、タイプ dynamic の式を含む操作をタイプ チェックしたり解決したりしないため、 を使用して変数が割り当てられることを保証できませんTryParse()

于 2013-04-30T17:34:02.943 に答える