我在 Jag Reeghal 的博客上阅读了这篇文章,在我看来,他的建议与使用对象初始化器并不一样。然后我意识到我真的不确定。
当一个对象被构造时,使用对象初始化器,并且这些初始化器之一抛出(可能是空引用异常)......对象实际上是构造的吗?这基本上就像在构造函数中抛出的异常吗?还是对象完全构造,然后初始化?
我在 Jag Reeghal 的博客上阅读了这篇文章,在我看来,他的建议与使用对象初始化器并不一样。然后我意识到我真的不确定。
当一个对象被构造时,使用对象初始化器,并且这些初始化器之一抛出(可能是空引用异常)......对象实际上是构造的吗?这基本上就像在构造函数中抛出的异常吗?还是对象完全构造,然后初始化?
像这样的对象初始化语句var x = new Foo { Property1 = 5};
将被实现为如下所示:
Foo temp = new Foo();
temp.Property1 = 5;
x = temp;
如您所见,initiallizer 中的属性是在构造对象后设置的,但是在设置所有属性之前不会将变量设置为完全初始化的对象,因此如果抛出异常,构造的对象就会丢失即使捕获到异常(变量将保留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并不总是一样的!!
区别在于调试/发布构建配置。
如果你不相信我,请看一下反光板......