C# 分配给接口数组初始化器编译,但为什么?
今天我在想,制作匿名对象是一种很好的接口类型,我已经看到了,所以我不是唯一的一个 在我开始检查发生了什么之前,我写了一些代码,如下所示。 有趣的是,我使用的是.NETFramework4,我知道匿名对象无法实现接口,但我还没有看到VS对这段代码的抱怨 更好的是,当我用大括号括起来时,IntelisSense会找到我接口的“属性”,就像它是有效代码一样 为什么这篇文章正在编译,当它运行时,它给出了空引用异常C# 分配给接口数组初始化器编译,但为什么?,c#,C#,今天我在想,制作匿名对象是一种很好的接口类型,我已经看到了,所以我不是唯一的一个 在我开始检查发生了什么之前,我写了一些代码,如下所示。 有趣的是,我使用的是.NETFramework4,我知道匿名对象无法实现接口,但我还没有看到VS对这段代码的抱怨 更好的是,当我用大括号括起来时,IntelisSense会找到我接口的“属性”,就像它是有效代码一样 为什么这篇文章正在编译,当它运行时,它给出了空引用异常 namespace test { class Program {
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; }
}
}
您必须将实例分配给constractor中的someInterface;否则,它将为空。
Holder=newholder{someInterface={Property=1}//
Holder holder = new Holder { someInterface = { Property = 1 } };//<--Note you missed new keyword
创建匿名对象是一种很好的方式,它是某种接口类型
我知道并没有办法实现匿名对象接口,但我并没有看到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 } };
someInterface
初始化为无效值-这就是问题“为什么要编译”的关键所在?回答得好。仅供参考,这完全可以通过我刚找到的一个很棒的第三方库来实现+1为了完整起见,§7.6.10.1和§7.6.10.2中的C#5.0规范中描述了这一点。@MichaelPerrenoud这是我上周在寻找类似功能时发现的一段很好的代码:)@Adriano谢谢,我想知道你们如何指出规范的确切部分!有时我甚至不知道该功能的确切名称:(一个小的更正,这相当于Holder temp=new Holder();temp.someInterface.Property=1;Holder Holder=temp;
。属性赋值发生在Holder
初始化之前。想象一下,如果Holder
是一个静态字段,您不会期望属性能够读取该字段并获取新对象,对吗?
class Holder
{
public Holder()
{
someInterface = new Class();
}
public ISomeInterface someInterface{get; set;}
}
Holder holder = new Holder { someInterface = { Property = 1 } };