Назначить для инициализатора интерфейса массива компиляции, но почему?
Сегодня я думал, что было бы аккуратно создавать анонимный объект, который является типом некоторого интерфейса, и я видел на SO, что я не один.
Прежде чем я начал проверять, что происходит, я написал код, подобный приведенному ниже.
К моему развлечению он скомпилирован, я использую .net framework 4, и я знаю, что не существует интерфейса для реализации анонимных объектов, но я не видел жалобы от VS об этом коде.
Еще лучше, когда я устанавливаю брекеты, что intelisense находит "Свойство" моего интерфейса, точно так же, как это было бы правильным кодом.
Почему эта компиляция компилируется, и когда она запускается, она дает исключение ссылочной ссылки?
namespace test
{
class Program
{
static void Main(string[] args)
{
Holder holder = new Holder { someInterface = { Property = 1 } };
Console.WriteLine(holder.someInterface.Property);
}
}
class Holder
{
public ISomeInterface someInterface{get; set;}
}
interface ISomeInterface
{
int Property { get; set; }
}
}
Ответы
Ответ 1
Holder holder = new Holder { someInterface = { Property = 1 } };//<--Note you missed new keyword
Выше строки равно
Holder temp = new Holder();
temp.someInterface.Property = 1;
Holder holder = temp;// <--Here someInterface is null so you get null reference exception.
Это должно быть что-то вроде
Holder holder = new Holder { someInterface = new SomeClass(){ Property = 1 } };//<--Note the new keyword here
Примечание. Ваш код никогда не вводил "Анонимный тип". Это "Инициализатор объектов".
Когда вы используете синтаксис ObjectInitializer с ключевым словом new
, это означает, что вы устанавливаете что-то, когда используете синтаксис ObjectInitializer без ключевого слова new
, это означает, что вы читаете что-то.
Ответ 2
было бы аккуратно создавать анонимный объект, который является типом некоторого интерфейса,
Я знаю, что не существует интерфейса для реализации анонимных объектов, но я не видел жалобы от VS об этом коде.
Проблема заключается в том, что вы предполагаете, что следующий код создает новый экземпляр анонимного типа
new Holder { someInterface = { Property = 1 } };
{ Property = 1 }
не создает новый экземпляр анонимного типа - это инициализатор объекта.
Если вы замените свой код на правильную конкретизацию анонимного типа, тогда компилятор будет жаловаться на то, что экземпляр не может быть неявно преобразован в ISomeInterface
, как вы ожидали.
new Holder { someInterface = new { Property = 1 } };
Ответ 3
Стоит отметить, почему компилятор разрешает это поведение. Причиной someInterface
может быть не всегда null
. Это то, что синтаксис инициализатора объекта переводится на:
Holder temp = new Holder(); //creates temp object calling default constructor
temp.someInterface = yourValue;
holder = temp; //finally assigned back to your variable.
В вашем случае someInterface
остается неинициализированным. Но это не обязательно, если у вас есть пустой конструктор, инициализирующий someInterface
правильно.
class Holder
{
public Holder()
{
someInterface = new Class();
}
public ISomeInterface someInterface{get; set;}
}
Теперь это работает:
Holder holder = new Holder { someInterface = { Property = 1 } };
Ответ 4
Вы должны назначить экземпляр someInterface в конструкторе Holder; в противном случае он будет равен нулю.