次のようなコードを使用すると、コンパイラはc.MyProperty
に対して文句を言います。
MyClass c;
try { throw new Exception(); }
catch (Exception) { }
c.MyProperty = 2; // "Use of unassigned local variable 'c'".
ただし、初期化でnull
をc
に割り当てても文句は言いません。
MyClass c = null;
try { throw new Exception(); }
catch (Exception) { }
c.MyProperty = 2; // no complains this time.
では、なぜこれが機能するのでしょうか? c
にnull
が割り当てられておらず、仮にコンパイラがそれを許可した場合、c.MyProperty
で同じ例外がスローされません。オブジェクト参照がオブジェクトのインスタンス?
null
を変数に割り当てると、コンパイラーに彼よりもよく知っているので、彼はこれについて文句を言うべきではないので、バックオフするように伝えています。
これはおそらく、null
の割り当てが開発者による明示的なアクションを意味すると見なされるという事実によるものです。
このように考えると、コンパイラは、null参照をスローするためコンパイルできないことをユーザーに通知せず、コンパイルに必要な条件の1つが満たされていない、つまり、間違いなく割り当てられます。
仕様によると、nullはc#リテラルです:「null-literalは暗黙的に参照型またはnull許容型に変換できます」
割り当ての面でも:(仕様から取得)
仕様から引用した引用の開始
5.3.明確な割り当てを決定するための正確なルール使用される各変数が確実に割り当てられることを決定するには、コンパイラはこのセクションで説明されているプロセスと同等のプロセスを使用する必要があります。
コンパイラーは、最初に割り当てられていない変数が1つ以上ある各関数メンバーの本体を処理します。最初に割り当てられていない変数vごとに、コンパイラは関数メンバーの次の各ポイントでvの明確な割り当て状態を決定します。
・各ステートメントの冒頭
・各ステートメントのエンドポイント(§8.1)
・制御を別のステートメントまたはステートメントのエンドポイントに移動する各アーク
・各式の先頭
・各式の最後
引用の終わり
そのため、nullは実際にはメモリ内のオブジェクトを指していませんが、明確に割り当てられるという要件を満たしているため、コンパイラはそれを許可しています。
これは、C#言語仕様v。4.0のセクション1.6.6.2「メソッド本体とローカル変数」に次のように記述されているためです。
メソッド本体は、メソッドの呼び出しに固有の変数を宣言できます。このような変数はローカル変数と呼ばれます。
[スキップ]
C#では、値を取得する前に、ローカル変数を明確に割り当てられたにする必要があります。
これは、Binary Worrierがきちんと指摘しているように、あなたが足元で自分自身を撃たせないようにするためです。
この例外の理由は、変数にデフォルト値が割り当てられていないことです(例:
if (Request.Files != null && Request.Files.Count > 0)
{
Image = Request.Files.AllKeys[0];
}
var stream = new FileStream(Image,FileMode.Open);
現在、Image変数はコンパイラエラーを返します
未割り当てのローカル変数「Image」の使用
それは条件が真になる可能性があり、Image変数が何であるかを制御が知ることができないためです。そのため、elseブロックを配置するか、次のようにデフォルト値を割り当てます。
string Image = "";
if (Request.Files != null && Request.Files.Count > 0)
{
Image = Request.Files.AllKeys[0];
}
var stream = new FileStream(Image,FileMode.Open);