Domanda

I run into runtime NullReferenceException exception in the following code:

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

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

It's logical that compiller couldn't create interaface instance but I got a runtime exception, not a compile time. I was confused even more when I investigated this behavior further:

    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

Is this some kind of bug or I don't understand something? And I'm using .net framework 4.0

È stato utile?

Soluzione

It compiles, because compiler has no knowledge about is the List already initialized somewhere else. You can make it work by adding initialization into a constructor:

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

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

Or changing the property to hide a field, which is initialized when class instance is created:

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

Then, var container = new Container() { Items = { "Test" } }; works just fine.

At runtime .Add() method is called for every item in collection initializer group. When property is not initialized with new List<string> it has null value, and that's why NullReferenceException is thrown.

Object and Collection Initializers (C# Programming Guide)

By using a collection initializer you do not have to specify multiple calls to the Add method of the class in your source code; the compiler adds the calls.

Altri suggerimenti

you didn't initialize the List

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

By the way the below is legal as for the compiler there is nothing wrong with it (syntax is correct,etc)

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

but because the compiler doesn't know that Items list has not been initialized (you are not passing any item in the collection initializator {}) the .Add method won't be called on the List and the run-time won't know that the Items object is null

On the other hand the below is legal for the compiler but it throws an exception at run time because you try to initialize the the list passing an item (it is correct for the compiler for the same reason explained above) so when the run time will call the .Add method behind the scene, it will throw a null reference exception because Items has not been initialized

 var container = new Container() { Items = { "Test" } }; 
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top