Why Collection Initialization Throws NullReference

2020-04-10 04:37发布

问题:

The following code throws a NullReferenceException:

internal class Foo
{
    public Collection<string> Items { get; set; } // or List<string>
}

class Program
{
    static void Main(string[] args)
    {
        new Foo()
            {
                Items = { "foo" } // throws NullReferenceException
            };
    }
}
  1. Why don't collection initiliazers work in this case, although Collection<string> implements the Add() method, and why is NullReferenceException is thrown?
  2. Is it possible to get the collection initializer working, or is Items = new Collection<string>() { "foo" } the only correct way to initialize it?

回答1:

You never instantiated Items. Try this.

new Foo()
    {
        Items = new Collection<string> { "foo" }
    };

To answer your second question: You need to add a constructor and initialize Items over there.

internal class Foo
{    
    internal Foo()
    {
        Items  = new Collection<string>();
    }
    public Collection<string> Items { get; private set; }
}

Why your code throws NullReferenceException?



回答2:

Thanks guys. As summary collection initializer doesn't create instance of collection itself, but just uses Add() to add items to existant instance, and throws NullReferenceException if instance doesn't exist

1.

internal class Foo
{    
    internal Foo()
    {
        Items  = new Collection<string>();
    }
    public Collection<string> Items { get; private set; }
}

var foo = new Foo()
                {
                    Items = { "foo" } // foo.Items contains 1 element "foo"
                };

2.

   internal class Foo
    {    
        internal Foo()
        {
            Items  = new Collection<string>();
            Items.Add("foo1");
        }
        public Collection<string> Items { get; private set; }
    }

    var foo = new Foo()
                    {
                        Items = { "foo2" } // foo.Items contains 2 elements: "foo1", "foo2"
                    };


回答3:

In your Foo constructor you want to initialize collection.

internal class Foo
{
    public Foo(){Items = new Collection(); }
    public Collection<string> Items { get; set; } // or List<string>
}

class Program
{
    static void Main(string[] args)
    {
        new Foo()
            {
                Items = { "foo" } // throws NullReferenceException
            };
    }
}


回答4:

Foo.Items is declared, but an instance of Collection has never been assigned, so .Items is null.

Fix:

internal class Foo
{
    public Collection<string> Items { get; set; } // or List<string>
}

class Program
{
    static void Main(string[] args)
    {
        new Foo()
            {
                Items = new Collection<string> { "foo" } // no longer throws NullReferenceException :-)
            };
    }
}