为什么 name 在 shorthand 成员初始化的当前上下文中不存在?

Why doesn't name exist in the current context of shorthand member initialisation?

我正在为 st 对象使用对象初始值设定项:

public class Container 
{
    public Container () { ContainedItem = new Item; }
    public Item ContainedItem { get; set; }
}

public class Item
{
    public string Value { get; set; }
}

var MyContainer = new Container()
{
    // I want to populate the the property Value of the property Item
    // with the second line rather than the first
    ContainedItem = new Item() { Value = FooString }, // This works
    ContainedItem.Value = FooString  // This assigns to the same member but does not work
};

第二个初始化行给出了错误:

The name 'ContainedItem' does not exist in the current context.

Invalid initializer member declarator.

并建议在局部范围内的某处声明 ContainedItem

现在作为第一行,可以看出 ContainedItem 实际上是 Container 的有效 属性 并且 MyContainer.ContainedItem 绝对不是空的。 .那么为什么下面一行无法识别呢?

那是因为您试图在用于初始化对象成员的对象初始值设定项内部进行操作,而 c.x 不是对象 s 的已定义成员。因此出现上述错误。而是尝试在对象初始值设定项之外做它说

s.c.x = Bar[i].x;

您不能在初始值设定项中的赋值左侧使用 表达式,如 c.x。这包括方法调用以及 getters/setters:

var s = new S { x.MyMethod() };

可以在初始化器中做的唯一一件事就是设置一个属性 当前类型

来自MSDN

Object initializers let you assign values to any accessible fields or properties of an object

但是 c.x 不是 st 的字段或 属性,它甚至不是一个有效的名称。

不过这会起作用:

var s = new st();
{
    c = new ct()
};
s.c.x = Bar[i].x;

内联对象初始化的语法很明确。您不能只是编造东西并期望编译器能够理解。语法严格为:

{
    Property1 = Value1,
    Property2 = Value2,
    ...
}

c.x 不是 st 的 属性。 c 是。因此,你不能说 c.x = Bar[i].x

来自 C# 语言规范部分 7.6.10.2:

对象初始化器:<br> { 成员初始化器列表选项 } { 成员初始化列表 , } 成员初始化器列表: 成员初始化器 成员初始化器列表,成员初始化器 成员初始化器: 标识符 = 初始值 初始化值: 表达 对象或集合初始化器

您可以按原样为 "sub-properties" 赋值,只是不使用该语法。这是一个完整的例子:

using System;

public class Container
{
    public Item Item { get; set; } = new Item();
}

public class Item
{
    public string Value { get; set; }
}

class Test
{
    static void Main(string[] args)
    {
        var container = new Container
        {
            Item = { Value = "hello" }
        };
    }
}

Main 中的对象初始值设定项等同于:

var tmp = new Container();
tmp.Item.Value = "hello";
var container = tmp;

请注意,这依赖于 Container.Item 返回一个有效对象,而该对象没有在对象初始化程序中显式初始化 - 我的示例中就是这种情况,但并非如此 总是案例.