分配给接口数组初始化器编译但为什么?

今天我觉得制作一个接口类型的匿名对象是很好的,我在SO上看到我不仅仅是一个。

在我开始查看发生了什么之前,我写了一些代码如下所示。 为了我的娱乐它编译,我使用.net框架4,我知道没有办法做匿名对象实现接口,但我没有看到VS关于此代码的投诉。

更好的是,当我把括号intelisense发现我的界面的“属性”,就像它是有效的代码。

为什么这篇文章正在编译,何时运行它会给出null引用exception?

namespace test { class Program { static void Main(string[] args) { Holder holder = new Holder { someInterface = { Property = 1 } }; Console.WriteLine(holder.someInterface.Property); } } class Holder { public ISomeInterface someInterface{get; set;} } interface ISomeInterface { int Property { get; set; } } } 

 Holder holder = new Holder { someInterface = { Property = 1 } };//<--Note you missed new keyword 

上面的行等于

 Holder temp = new Holder(); temp.someInterface.Property = 1; Holder holder = temp;// <--Here someInterface is null so you get null reference exception. 

这应该是这样的

 Holder holder = new Holder { someInterface = new SomeClass(){ Property = 1 } };//<--Note the new keyword here 

注意:您的代码从未引入过“匿名类型”它是一个“对象初始化器”。

当您使用带有new关键字的ObjectInitializer语法时,这意味着您正在设置某些内容,当您使用没有new关键字的ObjectInitializer语法时,这意味着您正在阅读某些内容。

制作一些接口类型的匿名对象会很简洁,

我知道没有办法做匿名对象实现接口,但我没有看到VS对此代码的抱怨。

问题是,您假设以下代码创建了匿名类型的新实例

 new Holder { someInterface = { Property = 1 } }; 

{ Property = 1 }不会创建匿名类型的新实例 – 这是一个对象初始值设定项。

如果您使用匿名类型的正确实例替换代码,则编译器将抱怨实例不能像您预期的那样隐式转换为ISomeInterface

 new Holder { someInterface = new { Property = 1 } }; 

值得注意的是编译器为什么会出现这种行为。 someInterface的原因总是不能为null 。 这是对象初始化程序语法转换为:

 Holder temp = new Holder(); //creates temp object calling default constructor temp.someInterface = yourValue; holder = temp; //finally assigned back to your variable. 

在您的情况下, someInterface保持未初始化状态。 但是如果你的空构造函数正确初始化someinterface则不一定是这种情况。

 class Holder { public Holder() { someInterface = new Class(); } public ISomeInterface someInterface{get; set;} } 

现在这个工作:

 Holder holder = new Holder { someInterface = { Property = 1 } }; 

您必须在Holder约束器中为someInterface分配一个实例; 否则,它将为null。