2009-04-15 12 views

答えて

14

フィールドは、タイプの論理ゼロに自動的に初期化されます。これは暗黙的です。変数は「確定割り当て」に従わなければならないので、読み込む前にに割り当てる必要があります。

ECMAが静的フィールドまたはインスタンス フィールドであるかどうかを334v4

§17.4.4フィールドの初期化

フィールドの初期値は、デフォルト値(§12.2)でありますフィールドのタイプは です。 フィールドの値を観測する前に、 このデフォルト初期化が発生しました。 があり、フィールドは決して "未初期化"です。

§12。変数

... の値が得られる前に、変数が明確に割り当てられなければなりません(12.3項)。 ...

+0

。しかし、なぜ? –

+0

@YairHalberstadtは、「どうして? 1つはルールまたはルールの背後にある理由を意味します。最初の質問に答えましたが、これはおそらく質問に答えます。第2の理由は、コンストラクタチェーンを考慮した時点では、構築中に仮想メソッドが呼び出され、ILレベルのベースコンストラクタがコールチェーンのどのポイントでも呼び出せるということです。フィールドの初期化については分かりやすい。同様に、フィールドを重複させることができ、スペースをゼロにすることがさらに重要になるので、技術的にはinitは技術的に必要ではありません... –

+0

@YairHalberstadt @yairHalberstadtローカル変数は非常に簡単な代入チェックを持ちます。ゼロをスキップすることができます(ただし、現在のランタイムはIIRCを実行しません)。 –

4

実際には使用しないでください。あなたのエラーは、最初の行ではなく、2行目でなければなりません。

ここでコンパイラがお手伝いしています。

だから、それらを習慣として初期化しないで、代わりにコンパイラを助けてください!

これについての素晴らしいことは、あなたのために経路を確認することです。あなたがそれぞれの値を設定する3つのケースを持つswitch文を持っていても、 "default"に設定するのを忘れてしまいましたが、後でそれを使うとパスを逃したと警告します。

変数を0に初期化すると、その利点があります。

+0

初期化する前にtest1も使用しましたが、それは問題ありませんでした。 –

+0

はい、同じチェックはクラス変数には役立ちません。パスをトレースする方法はありません。コンストラクタに埋め込まれています(可能であれば良い考えです) –

+0

パスチェックはあまり面白くありませんが。例:uのようなものがあるとしましょう: 'bool a、b = true; if(b)a =真;ブールc = a; '。 3番目の声明**は、私たち人間が明らかに 'a' **が**によって**初期化されることをはっきりと見ても、エラーを生成します**。コンパイラは、条件が非常にシンプルで、常に真実であっても、内部の条件を調べません。 (したがって、より複雑なケースにも適用されます)。 – Sushi271

2

Marcが示しているように、仕様書にはそのことが記載されています。これが良いことである理由は、ローカル変数ではなく初期化されていないメンバを残しておく有効な理由があることです。その寿命はそのメソッドによって制限されています。変数は初期化するのに費用がかかり、特定の使用シナリオでのみ初期化する必要があります。私のために、背中が本当に壁にかかってしまうまで、初期化されていないメンバーは避けたいと思います。

ローカル変数の場合、すべてのコードパスが初期化につながる可能性があるかどうかを検出する方が簡単ですが、プログラム全体のすべてのコードパスが使用前に初期化されるかどうかを判断する優れたヒューリスティックはありません。完全に正しい答えはimpossible in both casesです。すべてのCS学生は知っておく必要があります。

12

Markの答えを拡張すると、ローカル変数の初期化は検証プロセスにも関連しています。
CLIは、検証可能なコード(つまり、SecurityPermission属性のSkipVerficationプロパティを使用して検証プロセスをスキップするように明示的に求められていないモジュール)では、すべてのローカル変数を使用前に初期化する必要があります。そうしないとVerficationExceptionがスローされます。

さらに興味深いことに、コンパイラはローカル変数を使用するすべてのメソッドに.locals initフラグを自動的に追加します。このフラグを指定すると、JITコンパイラはすべてのローカル変数をデフォルト値に初期化するコードを生成します。つまり、あなた自身のコードですでに初期化していても、JITはフラグ.locals initを遵守し、適切な初期化コードを生成します。この「重複初期化」は、最適化を可能にする構成ではJITコンパイラが重複を検出し、「デッドコード」として効果的に処理するため、パフォーマンスには影響しません(自動生成された初期化ルーチンは生成されたアセンブラ命令には表示されません)。

マイクロソフトによると(彼のブログの質問に応じてEric Lippertにバックアップされている)、ほとんどの場合、プログラマがローカル変数を初期化しないときには、変数を初期値に初期化するための基礎となる環境ですが、それは単に忘れてしまっただけであり、時には幻想的な論理的なバグを引き起こします。
この性質のバグがC#コードに現れる可能性を減らすために、コンパイラは依然としてローカル変数を初期化すると主張しています。生成されたILコードにフラグ.locals initを追加する予定ですが、このテーマに関する

より包括的な説明はここで見つけることができます:ちょうど質問を繰り返していますBehind The .locals init Flag

関連する問題