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

查看:121
本文介绍了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?

我的共享工具版本是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屋!

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