質問

Visual Studio に関して奇妙なことに気づきました。まず、関数のどこかにこれ (C#) を入力してみてください。

class Foo  
{  
    public void Bar()  
    {  
        string s;
        int i = s.Length;
    }
}

さて、すぐにマークされます ss.Length エラーとして、「Use of unassigned local variable 's'」。一方、次のコードを試してください。

class Foo  
{  
    private string s;
    public void Bar()  
    {  
        int i = s.Length;
    }
}

コンパイルされ、下線が引かれます sprivate string s 「」という警告とともにField 'Foo.s' is never assigned to, and will always have its default value null".

さて、VS がそれほど賢く、 s が常に null であることを知っているのであれば、なぜ 2 番目の例でその長さを取得することがエラーにならないのでしょうか?私の当初の推測は、「コンパイラが単にジョブを完了できない場合にのみコンパイル エラーが発生する。コードは技術的には Bar() を呼び出さない限り実行されるため、これは単なる警告です。」 ただし、その説明は最初の例によって無効になります。Bar() を呼び出さない限り、エラーなしでコードを実行できます。それで何が与えられるのでしょうか?単なる見落とし、それとも何か見落としがあるのでしょうか?

役に立ちましたか?

解決

最初の例(エラー)は、コンパイラの definite-assignment トラッキング。これはローカル変数にのみ適用されます。コンテキストが限られているため、コンパイラはこの状況をしっかりと把握しています。 s はnullではなく、未定義であることに注意してください。

2番目の例では、 s はフィールドです(デフォルトはnullです)。コンパイラエラーはありませんが、実行時に常にキャッチされます。この特定のケースはトラップされる可能性がありますが、この種のエラーは一般にコンパイラーによって検出されません。
たとえば、文字列を s に割り当てるメソッド Bar2()を追加できますが、 Bar()より後に呼び出すか、すべて。これにより、警告は削除されますが、実行時エラーは削除されません。

これは仕様によるものです。

他のヒント

2番目の例では、コードは有効ですが、正しく実行されない可能性があります。このプログラムが「正常に」実行できるいくつかのケースを以下に示します

  • コンパイラは完全に正しいわけではありません。 「s」は可能です。インスタンスがリフレクションによって変更された場合、null以外の値を持つようにします。
  • メソッドBarが呼び出されない場合、プログラムはエラーなしで実行できます
  • このプログラムは、テスト上の理由でNullReferenceExceptionをトリガーするテストプログラムである可能性があります

私ができる唯一の推測は、2番目の例では、リフレクションによってsを変更できるということです(BindingFlags.Privateを使用してプライベートメンバーにアクセスします)。

最初のサンプルでは s はローカル変数であり、コンパイラはそれを簡単にチェックできます。 s 変数は使用前に割り当てられませんでした。

2 番目のものでは、 s はグローバル変数であり、クラス内の別の場所で初期化された可能性があります。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top