为什么没有 new 的集合初始化器允许在对象初始化器内部而不是外部?

Why is a collection initializer without `new` allowed inside an object initializer but not outside?

我在初始化集合时注意到奇怪的行为 属性。

考虑:

class X
{
    public IList<int> Ints { get; set; }
}

我可以这样初始化Ints:

var theObject = new X
{
    Ints = { 12, 3, 4, 5, 6 }
};

但我做不到:

var x = new X();

x.Ints = { 12, 3, 4, 5, 6 }

知道为什么吗?看起来很不直观。

new X ...object creation expression 的开始。在这种表达式中,允许使用对象或集合初始值设定项:

object_creation_expression
    : 'new' type '(' argument_list? ')' object_or_collection_initializer?
    | 'new' type object_or_collection_initializer  // <--- here!
    ;

object_or_collection_initializer
    : object_initializer
    | collection_initializer
    ;

在您的代码中,您有一个 object initialiser { Ints = ... }. Inside that, there is another collection initialiser { 12, 3, 4, 5, 6 }。根据语法,这是允许的:

object_initializer
    : '{' member_initializer_list? '}'
    | '{' member_initializer_list ',' '}'
    ;

member_initializer_list
    : member_initializer (',' member_initializer)*
    ;

member_initializer
    : initializer_target '=' initializer_value
    ;

initializer_target
    : identifier
    | '[' argument_list ']'
    ;

initializer_value
    : expression
    | object_or_collection_initializer // <---- here!
    ;

initializer_value 可以是表达式,也可以是另一个 object_or_collection_initializer。这也意味着,尽管它们可能看起来像 object_or_collection_initializer,即 { 12, 3, 4, 5, 6 } 之类的东西不是一种表达方式。

另一方面,assignments不允许这样做。赋值只允许表达式在右侧:

assignment
    : unary_expression assignment_operator expression
    ;

正如评论中所指出的,这是一个集合初始值设定项的示例。

它确实是以下内容的语法糖:

var theObject = new X();
theObject.Items.Add(12);
theObject.Items.Add(3);
theObject.Items.Add(4);
theObject.Items.Add(5);
theObject.Items.Add(6);

任何适合'shape'的东西都可以这样初始化。 (本质上,它正在寻找一个 Add(...) 方法来匹配你的类型的正确签名。)你甚至可以用它来初始化字典集合。