我正在玩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);
}
}
所以,我有两个问题:
谢谢!
答案 0 :(得分:2)
实际问题与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 :(得分:1)
为什么我一直得到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
- 这是null并抛出NullReferenceException
。另一种方法是在Hazards
构造函数中创建一个新的空Chemical
集合 - 然后您可以保持当前代码不变:
public class Chemical
{
public Chemical()
{
_hazards = new List<Hazard>();
}
//..
}
答案 2 :(得分:1)
由于您来自PHP,或许对您概述CSharp的语法快捷方式会更有帮助!
乍一看它们真的很混乱,因为语法很相似。但是在快速介绍之后,你会学会爱他们。
Collection Initializer将项添加到集合中。语法为new SOMECOLLECTION { value, value, value }
填充集合的传统方法:
var items = new List<int>();
items.Add(1);
items.Add(2);
items.Add(3);
Collection Initializer 方式 - 这将编译为几乎完全相同的代码:
var items = new List<int>(){ 1, 2, 3 };
旁注:数组与列表 -
我会说List
更常用,因为它的大小可以改变。但这主要是个人偏好。创建数组的简便方法是:var items = new int[]{ 1, 2, 3 };
,但您也可以省略类型,编译器会解决它(也就是隐式类型数组):var items = new []{ 1, 2, 3 };
Object Initializer设置新对象的属性。语法为new SOMEOBJECT { Property = value, Property = value }
填充对象属性的传统方法:
var item = new Item();
item.First = "Chuck";
item.Last = "Norris";
对象初始化程序方式:
var item = new Item(){ First = "Chuck", Last = "Norris" };
我只是提到这一点,因为匿名对象的语法与其他对象非常相似,但是做了很多不同的事情。如果你不了解它们,它们会非常混乱!
语法看起来像Collection和Object Initializers的组合:new { AnyPropertyName = value, anyVariableNameBecomesAProperty, someOtherObject.SomeProperty }
让我解释一下!编译器将创建一个“匿名对象”,它具有3个属性AnyPropertyName
,anyVariableNameBecomesAProperty
和SomeProperty
,并以与Object Initializer相同的方式初始化值。如果未指定属性名称,则从源中推断出名称。
我希望这可以帮助您理解为什么new { h1, h2 }
(新匿名对象)与new []{ h1, h2 }
(新数组)不同。