繁体   English   中英

MVC3控制器中的NullReferenceException

[英]NullReferenceException in MVC3 Controller

我正在玩MVC3,尝试创建小型测试项目,这些项目将模拟我预期在从PHP迁移的较大项目中会遇到的问题。 在使用以下元素实例化项目中的“ model”变量时,我不断收到“ 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页面为起点。 为什么这样可以,但是我写的却不行? 当然,我没有测试这段代码,但是作者似乎很称职。

谢谢!

实际问题与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}

为什么我不断收到NullReferenceException,如何解决?

ICollection属性Hazards最初为ICollection创建模型时必须使用构造函数:

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 -这是null并抛出NullReferenceException 一种替代方法是在Chemical构造函数中创建一个新的空Hazards集合-然后您可以保留当前代码不变:

public class Chemical
{
    public Chemical()
    {
        _hazards = new List<Hazard>();
    }
    //..
}

由于您来自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";

对象初始化方式:

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

匿名对象

我之所以仅提及这一点,是因为匿名对象的语法与其他对象非常相似,但是却有很多不同。 如果您不了解它们,它们将非常令人困惑!

语法看起来像集合初始化和对象初始化的组合: new { AnyPropertyName = value, anyVariableNameBecomesAProperty, someOtherObject.SomeProperty }

让我解释! 编译器将创建一个“匿名对象”有3个属性, AnyPropertyNameanyVariableNameBecomesAPropertySomeProperty ,并初始化值的方式为对象初始化不相同。 如果未指定属性名称,则从源中推断出该名称。

我希望这可以帮助您理解为什么new { h1, h2 } (新匿名对象)与new []{ h1, h2 } (new数组)有何不同。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM