为什么不带"new"的集合初始值设定项允许在对象初始值设定器内部,而不允许在外部



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

考虑:

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
: 'new' type '(' argument_list? ')' object_or_collection_initializer?
| 'new' type object_or_collection_initializer  // <--- here!
;
object_or_collection_initializer
: object_initializer
| collection_initializer
;

在您的代码中,您有一个对象初始化程序{ Ints = ... }。在其中,还有另一个集合初始化程序{ 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 }这样的东西,并不是一种表达。

另一方面,作业不允许这样做。赋值只允许表达式位于右侧:

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

任何符合正确"形状"的东西都可以通过这种方式初始化。(重要的是,它正在寻找一个与您的类型的正确签名匹配的Add(...)方法。(您甚至可以使用它来初始化Dictionary集合。

相关内容

最新更新