Dominik
Dominik

Reputation: 1741

Why does an array initializer not work on a local variable?

Why is it possible to do the following without compiler-errors:

private class Foo
{
     public List<string> Bar { get; set; }
}

private void SomeRandomMethod(){
    var test2 = new Foo
    {
         Bar = { "test", "test2" }
    };
}

But this doesn't work?

List<string> test = { "test", "test2" };

I do know that i can write new { "test", "test2" }; and then it works. I don't want a workaround or a solution or something similar for this question, instead I'd like to have an explaination what the difference in those two cases exactly is.

EDIT: When changing the types from List<string> to string[] the first example doesn't compile anymore but the 2nd one does.

Thanks!

Upvotes: 3

Views: 202

Answers (1)

Selman Gen&#231;
Selman Gen&#231;

Reputation: 101681

The confusion here comes from the same syntax being treated as different in different contexts. In the object initializer, the expression represents a collection initializer.

The spec defines collection initializer as:

7.6.10.3 Collection initializers

A collection initializer consists of a sequence of element initializers, enclosed by { and } tokens and separated by commas. Each element initializer specifies an element to be added to the collection object being initialized, and consists of a list of expressions enclosed by { and } tokens and separated by commas.

Later in the same chapter:

For each specified element in order, the collection initializer invokes an Add method on the target object with the expression list of the element initializer as argument list, applying normal overload resolution for each invocation.

So this is why you get NRE in the first example. Since you don't add a new List<string> before using the collection initializer, you are attempting to call Add on a null object. You will either need to add new List<string> or do it in the constructor.

An array initializer is different, when you omit new there the compiler just adds new for you, so this:

string[] values = { "foo", "bar" };

is equivalent to:

string[] values = new [] { "foo", "bar" };

When you use { "foo", "bar" } outside of the object initializer you get the error because you are trying to assign an array to a list.

Note: In the collection initializer, you might expect the compiler to be smarter and add the new for you as in the array initializer but it might have other side effects. For example, if you are initializing the list in the constructor, it would overwrite the list. So I guess that's why it's the way it is.

Upvotes: 4

Related Questions