NullReferenceException 与 resharper 建议的对象初始值设定项
NullReferenceException with object initializer suggested by resharper
我对对象初始化程序语法有一个奇怪的问题。
这是我的样本 类:
public class Foo
{
public Bah BahProp { get; set; }
}
public class Bah
{
public int Id { get; set; }
}
考虑以下三种初始化对象的方法:
旧的、冗长但明确的方式,工作正常:
var foo1 = new Foo();
foo1.BahProp = new Bah();
foo1.BahProp.Id = 1;
// correctly initialized
我一直使用的第二种方式,使用 object initializer 语法:
var foo2 = new Foo
{
BahProp = new Bah { Id = 1 }
}; // correctly initialized
第三种方法 resharper 建议我的同事使用不同的 resharper 版本(这是错误吗?):
var foo3 = new Foo
{
BahProp = { Id = 1 }
}; // NullReferenceException
最后一种方法有何不同?
我的resharper版本是2016.1.1,同事是10.02。我的 resharper 建议采用第二种方式。但是第三种方式有什么作用,什么时候有用呢?
Update: 所以看起来使用最后一种方式是一个糟糕的resharper建议,这就是为什么他们同时将其更改为使用第二种方式。
如果你想使用第三种方法,你可以避免NullReferenceException
,方法是初始化所有properties/fields 内联或构造函数中的引用类型。
我绝对不会使用这种奇怪的属性赋值语法。
new Foo { BahProp = { Id = 1 } }
编译为:
new Foo().BahProp.Id = 1;
或者更详细一点:
var foo3 = new Foo();
foo3.BahProp.Id = 1;
所以 BahProp 为空。你没有构建它。
(这可能是所有 C# 中最令人困惑的语法)
选项 2 有效,因为您正在调用 Bah 的构造函数。
如果您在 Foo 的构造函数中初始化 BahProp,选项 3 也适用。它将在调用 BahProp = { Id = 1 }
时构建。
集合初始值设定项也是如此:
public class Foo {
public List<int> Numbers { get; set; }
}
var foo = new Foo { Numbers = { 1, 2, 3 } };
这不会初始化列表。它只在其上调用 Add。
您确实必须将 new MyObject() { X = 1, Y = 2 }
视为两个不同的部分:
new MyObject()
构造一个新对象并且
{ X = 1, Y = 2 }
设置其属性的值(仅此而已)。
对象和集合初始值设定项可以嵌套。顶级初始化器必须遵循构造函数,但嵌套初始化器不需要。
我对对象初始化程序语法有一个奇怪的问题。
这是我的样本 类:
public class Foo
{
public Bah BahProp { get; set; }
}
public class Bah
{
public int Id { get; set; }
}
考虑以下三种初始化对象的方法:
旧的、冗长但明确的方式,工作正常:
var foo1 = new Foo();
foo1.BahProp = new Bah();
foo1.BahProp.Id = 1;
// correctly initialized
我一直使用的第二种方式,使用 object initializer 语法:
var foo2 = new Foo
{
BahProp = new Bah { Id = 1 }
}; // correctly initialized
第三种方法 resharper 建议我的同事使用不同的 resharper 版本(这是错误吗?):
var foo3 = new Foo
{
BahProp = { Id = 1 }
}; // NullReferenceException
最后一种方法有何不同?
我的resharper版本是2016.1.1,同事是10.02。我的 resharper 建议采用第二种方式。但是第三种方式有什么作用,什么时候有用呢?
Update: 所以看起来使用最后一种方式是一个糟糕的resharper建议,这就是为什么他们同时将其更改为使用第二种方式。
如果你想使用第三种方法,你可以避免NullReferenceException
,方法是初始化所有properties/fields 内联或构造函数中的引用类型。
我绝对不会使用这种奇怪的属性赋值语法。
new Foo { BahProp = { Id = 1 } }
编译为:
new Foo().BahProp.Id = 1;
或者更详细一点:
var foo3 = new Foo();
foo3.BahProp.Id = 1;
所以 BahProp 为空。你没有构建它。
(这可能是所有 C# 中最令人困惑的语法)
选项 2 有效,因为您正在调用 Bah 的构造函数。
如果您在 Foo 的构造函数中初始化 BahProp,选项 3 也适用。它将在调用 BahProp = { Id = 1 }
时构建。
集合初始值设定项也是如此:
public class Foo {
public List<int> Numbers { get; set; }
}
var foo = new Foo { Numbers = { 1, 2, 3 } };
这不会初始化列表。它只在其上调用 Add。
您确实必须将 new MyObject() { X = 1, Y = 2 }
视为两个不同的部分:
new MyObject()
构造一个新对象并且
{ X = 1, Y = 2 }
设置其属性的值(仅此而已)。
对象和集合初始值设定项可以嵌套。顶级初始化器必须遵循构造函数,但嵌套初始化器不需要。