是在初始化式抛出时构造的对象

本文关键字:对象 初始化 | 更新日期: 2023-09-27 17:50:20

我在Jag Reeghal的博客上阅读了这篇文章,在我看来,他所建议的与使用对象初始化式并不是一回事。然后我意识到我真的不确定。

当用对象初始化器构造对象时,其中一个初始化器抛出(可能是Null Reference异常)…对象实际上被构造了吗?这基本上就像构造函数中抛出的异常吗?还是对象完全构造,然后初始化?

是在初始化式抛出时构造的对象

var x = new Foo { Property1 = 5};这样的对象初始化语句将像这样实现:

Foo temp = new Foo();
temp.Property1 = 5;
x = temp;

正如你所看到的,初始化器中的属性是在对象构造之后设置的,然而变量并没有被设置为完全初始化的对象,直到所有属性被设置,所以如果一个异常被抛出,即使异常被捕获,构造的对象也会丢失(变量将保持null或之前的任何值)。

首先完全构造,然后初始化。然而,如果抛出异常,您将永远不会获得对这样一个对象的引用,编译器确保您的引用只能引用正确初始化的对象。它使用一个临时变量来保证这一点。

例如,这段代码:

var obj = new Model {
   FirstName = reader[0].ToString(),
   LastName = reader[1].ToString(),
   Age = Convert.ToInt32(reader[2].ToString())
};

被编译器重写为:

var temp = new Model();
temp.FirstName = reader[0].ToString();
temp.LastName = reader[1].ToString();
temp.Age = Convert.ToInt32(reader[2].ToString())
var obj = temp;

对象将被构造,但初始化不会完成。初始化只是一个编译器的技巧;看看生成的IL,你会发现两者都是一样的。这篇博文抱怨说很难判断异常发生在哪一行,但我个人从来没有遇到过这种困难。

你都需要意识到编译后的IL并不总是相同的!!

区别在于调试/发布构建配置。

如果你不相信我,就看看反光镜.....