2

次のコードがあります:

  static void Main(string[] args)
  {
     byte currency;
     decimal amount;
     if (Byte.TryParse("string1", out currency) && Decimal.TryParse("string2", out amount))
     {
        Check(currency, amount);
     }
     Check(currency, amount); // error's here
  }

  static void Check(byte b, decimal d) { }

そして次のエラーを取得します:

割り当てられていないローカル変数 'amount' の使用

なぜ私はそれを取得していて、これは合法なのamountですか? currencyこの場合、なぜ割り当てられてamount- ではないのですか?

4

4 に答える 4

2

この行を見てください (2 行に分けました):

if (Byte.TryParse("string1", out currency) &&
    Decimal.TryParse("string2", out amount))

&&演算子は短絡評価です。つまり、最初の演算子がByte.TryParse成功しない場合、2 番目の演算子はDecimal.TryParseまったく実行されません。

currencyは、解析に失敗した場合に参照をデフォルト値にTryParse設定するため、常に割り当てられます。out currencyただし、amountこの場合は未定義のままです。次のようなコードを書いたようなものです。

if (Byte.TryParse("string1", out currency))
{
    if (Decimal.TryParse("string2", out amount))
    {
        Check(currency, amount);
    }
}
Check(currency, amount);

これにより、何が起こっているのかがより明確になるはずです。最初のifステートメント内の部分は常に実行され、値が に割り当てられcurrencyます。ネストされた2 番目のステートメント内の部分はif、最初のステートメントが成功した場合にのみ実行されます。そうしamountないと、2 番目のCheck.

を解析できない場合にデフォルト値を使用する場合はcurrency、ローカルをデフォルト値に初期化します。

byte currency = 0;
decimal amount = 0;
if (Byte.TryParse("string1", out currency) &&
    Decimal.TryParse("string2", out amount))
{
// Etc.

または、@Martin が言ったように、単純に両方を解析できます。

于 2010-02-18T22:52:51.217 に答える
1

これについては、C# 言語仕様の第 5.3 章で説明されています。これは分厚い章ですが、割り当てられていない「currency」変数に対してもコンパイラがエラーを出力するはずだったように思えます。if() ステートメントとブロックをコメントアウトすると、興味深いことに、コンパイラが突然賢くなります。コメントされたコードで「通貨」が使用されたことはありませんが。

それは正しくありません。バグを見つけたと思います。Eric Lippert が見過ごさない場合は、connect.microsoft.com でバグを報告できます。

于 2010-02-18T22:38:35.353 に答える
1

これは、割り当てられていない変数を使用しないようにすることを目的とした単なるコンパイラの警告です (ただし、あなたはそれを理解していると思います)。割り当てられていない変数の1つを使用し、他の変数を使用しない場合にのみ取得する理由を説明できません。

于 2010-02-18T22:08:29.560 に答える
0

amountこれは、コンパイラが初期値が割り当てられることを保証できないプログラム内のパスがあるために発生します。つまり、最初のパスTryParse()が失敗したときです。そのため、使用しようとした行でエラーが発生しますamount

MSDN から:

out 引数として渡される変数は、初期化する必要はありません。ただし、メソッドが戻る前に out パラメータに値を割り当てる必要があります。

ローカル変数にデフォルト値を割り当てることで回避できます。

 decimal amount = 0;

それ以外の場合は、両方のTryParse()呼び出しがいずれの場合でも行われるようにする必要があります。たとえば、(あまり良いコードではありません):

bool b1 = Byte.TryParse("string1", out currency);
bool b2 = Decimal.TryParse("string2", out amount);

if (b1 && b2) {...}

aところで、値が割り当てられていないため、このコード フラグメントでも同じコンパイラ エラーが発生します。

int a, b=1;
int c = a+b;
于 2010-02-18T22:07:04.963 に答える