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

时间:2013-12-19 14:36:37

标签: c#

今天我觉得制作匿名对象是一种接口类型是很好的,我在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; }
    }
}

4 个答案:

答案 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构造函数中为同一个接口分配一个实例;否则,它将为空。