Я считаю, что ключевая вещь, которую нужно понять, это то, что в игре есть два синтаксических вкуса сахара (или, по крайней мере, так должно быть):
- Инициализация объекта
- Инициализация коллекции
Заберите List
на мгновение и посмотрите на поле как на объект:
public class Foo
{
public object Bar { get; set; }
}
При использовании Инициализация объекта , вы назначаетеobject (или null):
var foo = new Foo()
{
Bar = new object(); //or Bar = null
}
Теперь вернемся к исходному примеру и добавим Инициализация коллекции поверх этого.На этот раз компилятор понимает, что это свойство реализует IEnumerable
, и предоставленный вами массив имеет правильный тип, поэтому он пытается вызвать метод Add
интерфейса.Сначала он должен искать объект, который в вашем случае равен null
, потому что вы не инициализировали его внутри.Если вы выполните отладку через это, вы обнаружите, что получатель вызывается и возвращает null
, что приводит к ошибке.
Правильный способ смешивания обеих функций будет для вас назначением new объект, который вы инициализируете своими значениями:
var foo = new Foo()
{
Bar = new List<string>(){ "one", "two" }
};
Если вы отладите эту версию, вы обнаружите, что вместо этого вызывается установщик с новым инициализированным экземпляром.
В качестве альтернативы,вы можете инициализировать ваше свойство внутренне:
public List<string> Bar { get; set; } = new List<string>();
Если вы отладите эту версию, вы обнаружите, что свойство сначала инициализируется значением, а ваша версия кода затем выполняется без ошибок (сначала вызывая получатель):
var foo = new Foo()
{
Bar = {"one", "two"}
};
Чтобы проиллюстрировать синтаксический аспект сахара, Инициализация коллекции работает только в пределах оператора вызова конструктора:
List<string> bar = {"one", "two" }; //ERROR: Can only use array initializer expressions to assign to array types. Try using a new expression instead.
List<string> bar = new[] { "one", "two" }; //ERROR: Cannot implicitly convert type 'string[]' to 'System.Collections.Generic.List<string>'
List<string> bar = new List<string>() { "one", "two" }; //This works!
Если вы хотитеразрешить инициализацию, как в исходном примере, тогда ожидается, что переменная будет установлена в экземпляр до Add
meэто можно назвать.Это правда, используете ли вы синтаксический сахар или нет.С тем же успехом я мог бы столкнуться с той же ошибкой, выполнив следующее:
var foo = new Foo();
foo.Bar.Add("one");
Так что вы можете инициализировать переменную для охвата всех баз, если, конечно, значение null
не имеет семантического значенияв вашем приложении.