首页 > 解决方案 > C# 嵌套对象初始化器

问题描述

C# 5.0 语言规范 7.6.10.2对象初始化器声明

在等号之后指定对象初始化器的成员初始化器是嵌套对象初始化器,即嵌入对象的初始化。嵌套对象初始值设定项中的赋值不是为字段或属性分配新值,而是被视为对字段或属性成员的赋值。嵌套对象初始值设定项不能应用于具有值类型 的属性或具有值类型的只读字段

虽然我知道在构造函数运行后初始化程序无法修改只读字段,但我对属性的限制一无所知。

以下是我用来测试此属性限制的代码示例:

using System;

namespace ObjectCollectionInitializerExample
{
    struct MemberStruct
    {
        public int field1;
        public double field2;
    }
    class ContainingClass
    {
        int field;
        MemberStruct ms;
        public int Field
        {
            get { return field; }
            set { field = value; }
        }
        public MemberStruct MS
        {
            get { return ms; }
            set { ms = value; }
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            // Nested object initializer applied to a property of value type compiles!
            ContainingClass cc = new ContainingClass { Field = 1, MS = new MemberStruct { field1 = 1, field2 = 1.2} };
            Console.ReadKey();
        }
    }
}

我评论了应该根据规范生成编译器错误的代码。但它编译成功。我在这里想念什么?

谢谢

标签: c#object-initializers

解决方案


您拥有的不是嵌套对象初始化程序,因为您显式创建了 MemberStruct 的新实例。内部对象初始值设定项不直接跟在等号之后,而是一个自身的对象初始值设定项,与对 MemberStruct 构造函数的调用相关联。

这就是使用嵌套对象初始化器的样子:

ContainingClass cc = new ContainingClass { Field = 1, MS = { field1 = 1, field2 = 1.2} };

当 MS 是值类型(结构)时,这不会编译,但当 MS 是引用类型(对象)时,它会编译。


推荐阅读