NullReferenceException в контроллере MVC3 - PullRequest
0 голосов
/ 10 сентября 2011

Я играю с MVC3, пытаюсь создать небольшие тестовые проекты, которые имитируют проблемы, с которыми я столкнусь, в более крупном проекте, который я переношу с PHP.Я продолжаю получать NullReferenceException при создании экземпляра переменной "модель" в проекте с элементами ниже:

Модель:

public class MainModel
{
    public IEnumerable<Chemical> chemicals { get; set; }

}

public class Chemical
{
    public int ChemicalId { get; set; }
    public string Name { get; set; }

    public virtual ICollection<Hazard> Hazards { get; set; }

}

public class Hazard
{
    public int HazardId { get; set; }
    public string Description { get; set; }

    public virtual ICollection<Chemical> Chemicals { get; set; }
}

Контроллер:

public class MainController : Controller
{

    public ActionResult Index()
    {

        var h1 = new Hazard { HazardId = 1, Description = "Flammable" };
        var h2 = new Hazard { HazardId = 2, Description = "Carcinogen" };
        var h3 = new Hazard { HazardId = 3, Description = "Water Reactive" };

        var model = new [] {
            new Chemical { ChemicalId = 1, Name = "Benzene", Hazards = {h1, h2}},
            new Chemical { ChemicalId = 2, Name = "Sodium", Hazards = { h3 } },
            new Chemical { ChemicalId = 3, Name = "Chloroform", Hazards =  { h2 } },
            new Chemical { ChemicalId = 4, Name = "Water" }
        }; //NULL EXCEPTION THROWN HERE

        return View(model);
    }

}

Итак, у меня есть два вопроса:

  1. Почему я продолжаю получать исключение NullReferenceException и как его можно исправить?
  2. При написании этого кода я использовал эту страницу StackOverFlow в качестве отправной точки.Почему это хорошо, а то, что я написал, нет?Конечно, я не тестировал этот код, но автор кажется очень компетентным.

Спасибо!

Ответы [ 3 ]

2 голосов
/ 10 сентября 2011

Фактическая проблема не имеет ничего общего с MVC.Вы создаете экземпляр ICollection Hazards с анонимным объектом, и я считаю, что компилятор не разрешает этот код должным образом, так что он завершается с ошибкой во время выполнения.Вот быстрое решение:

var model = new [] {
    new Chemical { ChemicalId = 1, Name = "Benzene", Hazards = new List<Hazard>{h1, h2}},
    new Chemical { ChemicalId = 2, Name = "Sodium", Hazards = new List<Hazard>{ h3 } },
    new Chemical { ChemicalId = 3, Name = "Chloroform", Hazards =  new List<Hazard>{ h2 } },
    new Chemical { ChemicalId = 4, Name = "Water" }
};

Обратите внимание на использование List<Hazards>{h1, h2} вместо просто {h1, h2}.

1 голос
/ 11 сентября 2011

Поскольку вы работаете с PHP, возможно, было бы более полезно дать вам обзор сочетаний клавиш синтаксиса CSharp!
На первый взгляд они действительно сбивают с толку, потому что синтаксис очень похож. Но после короткого вступления вы научитесь их любить.

Коллекция инициализаторов

Инициализатор коллекции добавляет элементы в коллекцию. Синтаксис new SOMECOLLECTION { value, value, value }

Традиционный способ заполнения коллекции:

var items = new List<int>();
items.Add(1);
items.Add(2);
items.Add(3);

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

var items = new List<int>(){ 1, 2, 3 };

Примечание: Массив против списка - Я бы сказал, что List чаще используется, потому что его размер может измениться. Но это в основном личные предпочтения. Сокращенный способ создания массива: var items = new int[]{ 1, 2, 3 };, но вы также можете опустить тип, и компилятор выяснит это (он же неявно типизированный массив): var items = new []{ 1, 2, 3 };

Инициализаторы объектов

Инициализатор объекта устанавливает свойства нового объекта. Синтаксис new SOMEOBJECT { Property = value, Property = value }

Традиционный способ заполнения свойств объекта:

var item = new Item();
item.First = "Chuck";
item.Last = "Norris";

Инициализатор объектов way:

var item = new Item(){ First = "Chuck", Last = "Norris" };

Анонимные объекты

Я только упоминаю об этом, потому что синтаксис для анонимного объекта чрезвычайно похож на другие, но делает что-то очень, очень другое. Они очень запутаны, если вы о них не знаете!

Синтаксис выглядит как комбинация инициализаторов коллекции и объекта: new { AnyPropertyName = value, anyVariableNameBecomesAProperty, someOtherObject.SomeProperty }

Позвольте мне объяснить! Компилятор создаст «анонимный объект», который имеет 3 свойства AnyPropertyName, anyVariableNameBecomesAProperty и SomeProperty, и инициализирует значения так же, как это делает Object Initializer. Если вы не укажете имя свойства, оно будет выведено из источника.

Надеюсь, это поможет вам понять, почему new { h1, h2 } (новый анонимный объект) НАСТОЛЬКО отличается от new []{ h1, h2 } (новый массив).

1 голос
/ 10 сентября 2011

Почему я продолжаю получать исключение NullReferenceException и как его можно исправить?

Свойство ICollection Hazards изначально равно нулю - вам нужно использовать конструктор, когда высоздайте свою модель:

var model = new[] {
    new Chemical { ChemicalId = 1, Name = "Benzene", Hazards = new List<Hazard>() {h1, h2}},
    new Chemical { ChemicalId = 2, Name = "Sodium", Hazards = new List<Hazard>(){ h3 } },
    new Chemical { ChemicalId = 3, Name = "Chloroform", Hazards =  new List<Hazard>(){ h2 } },
    new Chemical { ChemicalId = 4, Name = "Water" }
};

Код, который вы в данный момент имеете, попытается добавить т.е. {h1,h2} к Hazards - что равно нулю, и выведите NullReferenceException.Альтернативой является создание новой пустой коллекции Hazards в конструкторе Chemical - тогда вы можете оставить свой текущий код без изменений:

public class Chemical
{
    public Chemical()
    {
        _hazards = new List<Hazard>();
    }
    //..
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...