Resharper建议使用带有对象初始化程序的NullReferenceException [英] NullReferenceException with object initializer suggested by resharper
问题描述
对象初始化器语法有一个奇怪的问题.
I have a strange issue with the object initializer syntax.
这是我的示例课程:
public class Foo
{
public Bah BahProp { get; set; }
}
public class Bah
{
public int Id { get; set; }
}
考虑以下三种初始化对象的方法:
Consider following three ways to initialize an object:
旧的,冗长但显式的方式可以正常工作:
The old, verbose but explicit way, working correctly:
var foo1 = new Foo();
foo1.BahProp = new Bah();
foo1.BahProp.Id = 1;
// correctly initialized
我一直使用的第二种方法,使用对象初始化程序语法:
The second way i'm always using, using object initializer syntax:
var foo2 = new Foo
{
BahProp = new Bah { Id = 1 }
}; // correctly initialized
Resharper的第三种方式建议我的同事使用其他版本的Resharper(这是一个错误吗?):
A third way resharper has suggested my collegue with a different resharper version(is it a bug?):
var foo3 = new Foo
{
BahProp = { Id = 1 }
}; // NullReferenceException
最后一种方法有何不同?
What is the last approach doing differently?
我的共享工具版本是2016.1.1,我的同事是10.02.我的剃须刀建议了第二种方法.但是第三种方法做什么,什么时候有用?
My resharper version is 2016.1.1, my colleague was on 10.02. My resharper suggested the second way. But what does the third way do and when is it useful?
更新:因此使用第一种方法似乎是一种不好的建议,这就是为什么他们同时使用第二种方法更改了它的原因.
Update: So it seems that it was a bad resharper sugestion to use the last way, that's why they have changed it meanwhile to use the second way.
如果要使用第三种方法,可以通过初始化所有内联或构造函数中引用类型的属性/字段来避免使用NullReferenceException
.
You can avoid the NullReferenceException
if you want to use the third way by initializing all properties/fields that are reference types inline or in the constructor.
我绝对不会使用这种奇怪的属性赋值语法.
I will definitely not use this strange property assignment syntax.
推荐答案
new Foo { BahProp = { Id = 1 } }
编译为:
new Foo().BahProp.Id = 1;
或更详细些:
var foo3 = new Foo();
foo3.BahProp.Id = 1;
因此BahProp为空.您不是构造它.
(这可能是所有C#中最令人困惑的语法)
选项2起作用是因为您正在调用Bah的构造函数.
So BahProp is null. You're not constructing it.
(This is perhaps the most confusing syntax in all of C#)
Option 2 works because you're calling the constructor of Bah.
如果在Foo的构造函数中初始化BahProp,则选项3也将起作用.它将在调用BahProp = { Id = 1 }
时构建.
Option 3 would also work if you initialize BahProp inside the constructor of Foo. It will have been constructed by the time BahProp = { Id = 1 }
is called.
对于集合初始值设定项也是如此:
The same is seen with collection initializers:
public class Foo {
public List<int> Numbers { get; set; }
}
var foo = new Foo { Numbers = { 1, 2, 3 } };
这不会初始化列表.它只会调用添加".
This does not initialize the List. It only calls Add on it.
您确实必须将new MyObject() { X = 1, Y = 2 }
视为两个不同的部分:
new MyObject()
构造一个新对象,然后
{ X = 1, Y = 2 }
设置其属性的值(仅此而已).
对象和集合初始化器可以嵌套.顶层初始化程序必须遵循构造函数,但嵌套初始化程序则不需要.
You really must see new MyObject() { X = 1, Y = 2 }
as two distinct parts:
new MyObject()
constructs a new object and
{ X = 1, Y = 2 }
sets the values of its properties (and that's all it does).
Object and collection initializers can be nested. The top-level initializer must follow a constructor, but a nested initializer does not.
这篇关于Resharper建议使用带有对象初始化程序的NullReferenceException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!