为什么没有 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(...)
方法来匹配你的类型的正确签名。)你甚至可以用它来初始化字典集合。
我在初始化集合时注意到奇怪的行为 属性。
考虑:
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(...)
方法来匹配你的类型的正确签名。)你甚至可以用它来初始化字典集合。