2016-08-10 12 views
1

При использовании инициализатора объекта я попытался создать экземпляр ICollection через инициализатор массива по ошибке (я забыл часть new ...). Что странно, так это то, что компилятор не жаловался на время компиляции, но во время выполнения я получил исключение NullReferenceException.Инициализатор массива действителен во время компиляции, но не выполняется во время выполнения, когда внутри инициализатора объекта

Вот код, чтобы подвести итог ситуации:

public class FakeClass 
{ 
    public ICollection<string> StringsCollection { get; set; } 

    public string[] StringsArray { get; set; } 
} 

FakeClass c = new FakeClass(); 
c.StringsCollection = { "test" }; // doesn't compile - ok 
c.StringsCollection = new string[] { "test" }; // compiles - ok 
c.StringsArray = { "test" }; // doesn't compile - ok 
c.StringsArray = new string[] { "test" }; // compiles - ok 

string[] strings = { "sdfqgrt" }; // compiles - ok 
strings = { "sdfqgrt" }; // doesn't compile - ok 

FakeClass c2 = new FakeClass 
{ 
    StringsCollection = { "rthtj" }, // compiles and throws at run - why? 
    StringsArray = { "egryjt" } // doesn't compile - ok 
}; 

Конечно, я понимаю, почему этот код не может работать, но мне любопытно, как компилятор может принять такую ​​вещь.

+0

Вы используете {get; set}, который не инициализирует ICollection. Добавьте инициализацию в конструктор для класса или замените {get; set;} с вызовом конструктору: новый ICollection () – jdweng

+0

Инициализаторы используют приятный синтаксический сахар, слишком много сахара имеет тенденцию производить гнилые зубы. Синтаксис действителен, вы используете инициализатор * collection * (а не инициализатор поля), для этого требуется только метод Add(). Таким образом, он вызывает * getter *, а не setter для получения ссылки на сборку, это значение null. Избежать ошибок, подобных этому, не так просто, вам придется посещать школу Hard Knocks. –

ответ

2
StringsCollection = { "rthtj" } 

С кодом нет ничего плохого. Он вызывает неявный метод Add и добавляет строку в коллекцию.

NRE исключение из-за того, что ваше свойство еще не инициализировано.

Это будет работать

public ICollection<string> StringsCollection { get; set; } = new List<string>(); 

Update, чтобы ответить на комментарий

Для этого кода

FakeClass c = new FakeClass(); 
c.StringsCollection = new string[] { "test" }; 

FakeClass c2 = new FakeClass 
{ 
    StringsCollection = { "dd" } 
}; 

Посмотрите на IL и обратить внимание на различные между первой и второй StringCollection

IlSpy

Для setter случае вам нужно выражение как new string[] {} или новый список() для getter случае, если вы используете коллекцию инициализатор.

+0

Действительно, я где-то видел, что был вызван метод «Добавить». Но почему 'c.StringsCollection = {" test "};' даже не компилировать? –