I\'ve got a scenario I discovered when checking code coverage on a class\'s properties. When the property is of type List< T >, and an initializer is used, the set method
When using an initializer, like below, the set method on Text is called, and registers in code coverage, but the set method on Items does not, and I am wondering why:
That's because the Items list is not actually being initialized at the time the collection initializer is called. From section 7.6.10.2 of the spec:
A member initializer that specifies a collection initializer after the equals sign is an initialization of an embedded collection. Instead of assigning a new collection to the field or property, the elements given in the initializer are added to the collection referenced by the field or property.
This means that the collection initializer assumes that the collection has already been instantiated (which is true even outside of an object initializer). Remember that a collection initializer is nothing more than a series of .Add()
calls.
In order for your code to run without errors, Items must already have been initialized. This could have happened either in the property declaration itself (assuming it's an auto-implemented property):
public class ContainerClass
{
public string Text { get; set; }
public List<Item> Items { get; set; } = new List<Item>();
}
Or in the constructor (which you haven't shown):
public class ContainerClass
{
public string Text { get; set; }
public List<Item> Items { get; set; }
public ContainerClass()
{
Items = new List<Item>();
}
}
Otherwise, your code will throw a NullReferenceException as the program tries to evaluate the collection initializer.
Based on your statement that the setter never gets called for Items, it's likely it was initialized in the property declaration (or the backing field, if it's not actually an auto-implemented property). Had it been initialized in the constructor the setter would still have been called.
Your second example results in the setter being called because you are indeed assigning a new list to Items there.
You could do either:
public class ContainerClass
{
public string Text { get; set; }
public List<Item> Items { get; set; }
public ContainerClass()
{
Items = new List<Item>();
}
}
Then:
var arrange = new ContainerClass
{
Text = "SomeValue"
};
arrange.Items.Add(new Item(){Prop=Value});
Or, if you don't use the constructor as stated, you can initialize a list like so:
var arrange = new ContainerClass
{
Items = new List<Item>(){ new Item(){Prop=Value} }
};