如果初始化程序抛出,是否构造了一个对象?

我在Jag Reeghal的博客上阅读了这篇文章 。在我看来,他所建议的内容实际上与使用对象初始化器不同。 然后我意识到我确实不知道。

构造一个对象时,使用对象初始化器,并且其中一个初始化器抛出(可能是Null Referenceexception)……实际构造的对象是什么? 这基本上就像是在构造函数中抛出的exception吗? 或者是完全构造的对象,然后初始化?

一个对象初始化语句,如var x = new Foo { Property1 = 5}; 将实现如下:

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

如您所见,初始化器中的属性是在构造对象之后设置的,但是在设置了所有属性之前,变量未设置为完全初始化的对象,因此如果抛出exception,则构造的对象将丢失即使捕获了exception(变量将保持为null或之前的任何值)。

它首先完全构造,然后初始化。 但是,如果抛出exception,您将永远不会获得对此类对象的引用,编译器会确保您的引用只能引用正确初始化的对象。 它使用临时来保证这一点。

例如,这段代码:

 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,你会看到它的方式相同。 博客文章抱怨说,更难说出exception发生在哪一行,但我个人从来没有这么难过。

你们都需要知道编译的IL并不总是一样的!!

不同之处在于Debug / Release构建配置。

如果你不相信我的话,看一下reflection器……