如果初始化程序抛出,是否构造了一个对象?
我在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器……