使用 resharper 建议的对象初始化程序的 NullReferenceException [英] NullReferenceException with object initializer suggested by resharper

查看:44
本文介绍了使用 resharper 建议的对象初始化程序的 NullReferenceException的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对对象初始化器语法有一个奇怪的问题.

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?

我的 resharper 版本是 2016.1.1,我的同事是 10.02.我的 reshaper 提出了第二种方法.但是第三种方式有什么作用,什么时候有用呢?

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?

更新:所以使用最后一种方式似乎是一个糟糕的reshaper sugestion,这就是为什么他们同时改变它以使用第二种方式.

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 } };

这不会初始化列表.它只调用 Add 就可以了.

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆