今天我觉得制作匿名对象是一种接口类型是很好的,我在SO上看到我不仅仅是一个。
在我开始查看发生了什么之前,我写了一些代码,如下面的代码。 为了我的娱乐它编译,我使用.net框架4,我知道没有办法做匿名对象实现接口,但我没有看到VS对此代码的抱怨。
当我提出大括号时,智能感知更好的是找到我的界面的“属性”,就像它是有效的代码一样。
为什么这篇文章正在编译,何时运行它会给出null引用异常?
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; }
}
}
答案 0 :(得分:10)
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语法时,这意味着您阅读的东西。
答案 1 :(得分:2)
将匿名对象设置为某种接口的类型
我知道没有办法做匿名对象实现接口,但我没有看到VS对此代码的抱怨。
问题是,您假设以下代码创建了匿名类型的新实例
new Holder { someInterface = { Property = 1 } };
{ Property = 1 }
不会创建匿名类型的新实例 - 这是一个对象初始值设定项。
如果您使用匿名类型的正确实例替换代码,那么编译器会抱怨实例无法像您预期的那样隐式转换为ISomeInterface
。
new Holder { someInterface = new { Property = 1 } };
答案 2 :(得分: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 } };
答案 3 :(得分:0)
您必须在Holder构造函数中为同一个接口分配一个实例;否则,它将为空。