2013-03-20 2 views
3

Я бегу в выполнения NullReferenceException исключение в следующем коде:элемент коллекции Интерфейс странное поведение во время инициализации объекта

public class Container 
{ 
    public IList<string> Items { get; set; } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     var container = new Container() { Items = {"Test"} }; 
    } 
} 

Это логично, что compiller не удалось создать interaface инстанции, но я получил исключение во время выполнения, а не во время компиляции , Я смутился еще больше, когда я исследовал это поведение дальше:

var container = new Container() { Items = {} }; //Legal, Items is null after initialization 

    var container = new Container() { Items = { "Test" } }; //Legal, throws exception 
    container.Items = {}; //Illegal doesn't compile 
    container.Items = {"Test"}; //Illegal doesn't compile 

Является ли это какое-то ошибка или я не понимаю? И я использую .NET Framework 4.0

ответ

3

собирает, потому что компилятор не имеет знания о не является List уже инициализирован в другом месте. Вы можете сделать его работу путем добавления инициализации в конструкторе:

public class Container 
{ 
    public IList<string> Items { get; set; } 

    public Container() 
    { 
     Items = new List<string>(); 
    } 
} 

Или изменить свойство, чтобы скрыть поле, которое инициализируется при создании экземпляра класса:

private IList<string> items = new List<string>(); 
public IList<string> Items 
{ 
    get { return items; } 
    set { items = value; } 
} 

Затем var container = new Container() { Items = { "Test" } }; работает просто отлично ,

В процессе исполнения .Add() метод вызывается для каждого элемента в группе инициализатора коллекции. Когда свойство не инициализировано new List<string>, оно имеет значение null, и именно поэтому вызывается NullReferenceException.

Object and Collection Initializers (C# Programming Guide)

С помощью коллекции инициализатору вы не должны указать несколько вызовов метода Add класса в исходном коде; компилятор добавляет вызовы.

+0

Я всегда думал, что 'var container = new Container() {Items = {" Test "}}' создает коллекцию и добавляет элементы в коллекцию, я был неправ :( – Andrew

0

вы не инициализировать List

var container = new Container() { Items = new List<string>() { "Test" } }; 

Кстати ниже является законным, как и для компилятора нет ничего плохого с ним (синтаксис является правильным, и т.д.)

var container = new Container() { Items = {} }; 

а потому, что компилятор не знает, что Items список не был инициализирован (вы не проходит какой-либо элемент в коллекции initializator {}) .Add не будет вызываться на List, и время выполнения не будет знать, что объект Items имеет значение null

С другой стороны, нижеследующее является законным для компилятора, но оно выдает исключение во время выполнения, поскольку вы попробуйте инициализировать список, передающий элемент (это правильно для компилятора по той же причине, объясненной выше), поэтому, когда время выполнения вызовет метод .Add за сценой, он выкинет исключение нулевой ссылки, потому что Items не был инициализирован

var container = new Container() { Items = { "Test" } }; 
+1

Я думаю, что вопрос в том, почему первая строка - 'new Container() {Items = {}};' компилирует – Habib

+0

С новым списком это просто. Главный вопрос - почему он даже компилируется. – Andrew

+0

Я отредактировал свой ответ –

 Смежные вопросы

  • Нет связанных вопросов^_^