3

NullReferenceException次のコードでランタイム例外が発生しました。

public class Container
{
    public IList<string> Items { get; set; }
}

class Program
{
    static void Main(string[] args)
    {
        var container = new Container() { Items = {"Test"} };
    }
}

コンパイラがインターフェイスインスタンスを作成できなかったのは当然ですが、コンパイル時ではなく、ランタイム例外が発生しました。この動作をさらに調査すると、さらに混乱しました。

    var container = new Container() { Items = {} }; //Legal, Items is null after initialization

    var container = new Container() { Items = { "Test" } }; //Legal, throws exception
    container.Items = {}; //Illegal doesn't compile
    container.Items = {"Test"}; //Illegal doesn't compile

これはある種のバグですか、それとも私は何かを理解していませんか?そして、私は.netFramework4.0を使用しています

4

2 に答える 2

3

コンパイラはList既にどこかで初期化されていることを知らないため、コンパイルされます。コンストラクターに初期化を追加することで機能させることができます。

public class Container
{
    public IList<string> Items { get; set; }

    public Container()
    {
        Items = new List<string>();
    }
}

または、プロパティを変更して、クラス インスタンスの作成時に初期化されるフィールドを非表示にします。

private IList<string> items = new List<string>();
public IList<string> Items
{
    get { return items; }
    set { items = value; }
}

その後、var container = new Container() { Items = { "Test" } };問題なく動作します。

実行時.Add()に、コレクション初期化子グループ内のすべてのアイテムに対してメソッドが呼び出されます。プロパティが初期化されていないnew List<string>場合、値があり、それがスローされるnull理由です。NullReferenceException

オブジェクトとコレクションの初期化子 (C# プログラミング ガイド)

コレクション初期化子を使用すると、ソース コードでクラスの Add メソッドへの複数の呼び出しを指定する必要がなくなります。コンパイラは呼び出しを追加します

于 2013-03-20T09:59:22.987 に答える
0

初期化していないList

  var container = new Container() { Items = new List<string>() { "Test" } };

ちなみに、以下はコンパイラとしては合法であり、何も問題はありません(構文は正しいなど)

var container = new Container() { Items = {} }; 

ただし、コンパイラはItemsリストが初期化されていないことを認識していないため (コレクションの初期化子にアイテムを渡していないため{})、.Addメソッドは呼び出されずList、ランタイムはItemsオブジェクトが nullであることを認識しません。

一方、以下はコンパイラーにとっては正当ですが、項目を渡すリストを初期化しようとするため、実行時に例外がスローされます (上記で説明したのと同じ理由でコンパイラーにとっては正しいです)。バックグラウンドでメソッドを呼び出すと、初期化されていない.Addため、null 参照例外がスローされますItems

 var container = new Container() { Items = { "Test" } }; 
于 2013-03-20T09:55:42.450 に答える