I witnessed something strange when initializing a class with a List as a property. When doing this
var stuff = new Stuff(){list = {1, 2, 3} };
It compiles, and crashes saying that list is null. So, adding this to Stuff's constructor:
public Stuff(){
list = new List<int>();
}
List is now initialized to contain {1, 2, 3}
which seems to make some sense. But then, changing the constructor to
public Stuff(){
list = new List<int>(){1, 2, 3};
}
And initializing like so
var stuff = new Stuff(){list = {4, 5, 6} };
list is initialized to contain {1, 2, 3, 4, 5, 6}
leaving me rather confused.
It seems like this either shouldn't compile, or shouldn't behave this way. What exactly is going on here?
It seems like this either shouldn't compile, or shouldn't behave this way. What exactly is going on here?
Collection initializers work by calling the .Add
method on each item passed into the initializer. This adds them to the items you pre-populate within your constructor.
This is explained in the documentation for Collection Initializers:
Collection initializers let you specify one or more element initializers when you initialize a collection class that implements IEnumerable. The element initializers can be a simple value, an expression or an object initializer. 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.
This means the compiler turns your second call into something similar to:
var temp = new Stuff();
temp.list.Add(4);
temp.list.Add(5);
temp.list.Add(6);
Stuff stuff = temp;
As you can see, the stuff
variable will call the constructor normally (which adds 1
, 2
, and 3
), then add the other items, resulting in what you see.
You are initializing list
using a collection initializer. This way this works is given in the documentation:
Collection initializers let you specify one or more element initializers when you initialize a collection class that implements
IEnumerable
. The element initializers can be a simple value, an expression or an object initializer. By using a collection initializer you do not have to specify multiple calls to theAdd
method of the class in your source code; the compiler adds the calls.
In other words, this:
var stuff = new Stuff(){list = {1, 2, 3} };
is a shorthand way of writing this:
var temp = new Stuff();
temp.list.Add(1);
temp.list.Add(2);
temp.list.Add(3);
stuff = temp;
It's easy to see how this would cause a NullReferenceException
if list
is null
and how it appends to the existing items in the list, if any.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With