Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/269.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 分配给接口数组初始化器编译,但为什么?_C# - Fatal编程技术网

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

C# 分配给接口数组初始化器编译,但为什么?,c#,C#,今天我在想,制作匿名对象是一种很好的接口类型,我已经看到了,所以我不是唯一的一个 在我开始检查发生了什么之前,我写了一些代码,如下所示。 有趣的是,我使用的是.NETFramework4,我知道匿名对象无法实现接口,但我还没有看到VS对这段代码的抱怨 更好的是,当我用大括号括起来时,IntelisSense会找到我接口的“属性”,就像它是有效代码一样 为什么这篇文章正在编译,当它运行时,它给出了空引用异常 namespace test { class Program {

今天我在想,制作匿名对象是一种很好的接口类型,我已经看到了,所以我不是唯一的一个

在我开始检查发生了什么之前,我写了一些代码,如下所示。 有趣的是,我使用的是.NETFramework4,我知道匿名对象无法实现接口,但我还没有看到VS对这段代码的抱怨

更好的是,当我用大括号括起来时,IntelisSense会找到我接口的“属性”,就像它是有效代码一样

为什么这篇文章正在编译,当它运行时,它给出了空引用异常

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 } };