C# 嵌套初始化奇怪
C# Nested initialization strangeness
在这些初始化语句编译通过的前提下
List<int> l = new List<int> { 1, 2, 3 };
Dictionary<int, int> d = new Dictionary<int, int> { [1] = 11, [2] = 22 };
Foo f = new Foo { Bar = new List<int>() };
这不会
List<int> l = { 1, 2, 3 };
Dictionary<int, int> d = { [1] = 11, [2] = 22 };
Foo f = { Bar = new List<int>() };
我对嵌套初始化有疑问。鉴于以下 class
public class Foo {
public List<int> Bar { get; set; } = new List<int>();
public Dictionary<int, Foo> Baz { get; set; } = new Dictionary<int, Foo>();
}
我偶然发现你实际上可以这样做:
Foo f = new Foo {
Bar = { 1, 2, 3 },
Baz = {
[1] = {
Bar = { 4, 5, 6 }
}
}
};
虽然它编译它抛出 KeyNotFoundException
。所以我将属性更改为
public List<int> Bar { get; set; } = new List<int> { 4, 5, 6 };
public Dictionary<int, Foo> Baz { get; set; }
= new Dictionary<int, Foo> { [1] = new Foo { Bar = new List<int>() { 1, 2, 3 } } };
假设这是替换现有成员的一些不寻常的符号。现在初始化抛出一个 WhosebugException
.
所以我的问题是,为什么表达式甚至可以编译?它应该做什么?我觉得我一定错过了一些非常明显的东西。
So my question is, why does the expression even compile?
它是一个带有集合初始化器值的对象初始化器。来自 C# 规范部分 7.6.10.2:
A member initializer that specifies a collection initializer after the equals sign is an initialization of an embedded collection. Instead of assigning a new collection to the field or property, the elements given in the initializer are added to the collection referenced by the field or property.
所以你的code代码大致相当于:
Foo tmp = new Foo();
tmp.Bar.Add(1);
tmp.Bar.Add(2);
tmp.Bar.Add(3);
tmp.Baz[1].Bar.Add(4); // This will throw KeyNotFoundException if Baz is empty
tmp.Baz[1].Bar.Add(5);
tmp.Baz[1].Bar.Add(6);
Foo f = tmp;
您的初始化版本将抛出 WhosebugException
,因为 Foo
的初始化程序需要创建 Foo
的新实例,而后者需要创建 [=12= 的新实例]等
在这些初始化语句编译通过的前提下
List<int> l = new List<int> { 1, 2, 3 };
Dictionary<int, int> d = new Dictionary<int, int> { [1] = 11, [2] = 22 };
Foo f = new Foo { Bar = new List<int>() };
这不会
List<int> l = { 1, 2, 3 };
Dictionary<int, int> d = { [1] = 11, [2] = 22 };
Foo f = { Bar = new List<int>() };
我对嵌套初始化有疑问。鉴于以下 class
public class Foo {
public List<int> Bar { get; set; } = new List<int>();
public Dictionary<int, Foo> Baz { get; set; } = new Dictionary<int, Foo>();
}
我偶然发现你实际上可以这样做:
Foo f = new Foo {
Bar = { 1, 2, 3 },
Baz = {
[1] = {
Bar = { 4, 5, 6 }
}
}
};
虽然它编译它抛出 KeyNotFoundException
。所以我将属性更改为
public List<int> Bar { get; set; } = new List<int> { 4, 5, 6 };
public Dictionary<int, Foo> Baz { get; set; }
= new Dictionary<int, Foo> { [1] = new Foo { Bar = new List<int>() { 1, 2, 3 } } };
假设这是替换现有成员的一些不寻常的符号。现在初始化抛出一个 WhosebugException
.
所以我的问题是,为什么表达式甚至可以编译?它应该做什么?我觉得我一定错过了一些非常明显的东西。
So my question is, why does the expression even compile?
它是一个带有集合初始化器值的对象初始化器。来自 C# 规范部分 7.6.10.2:
A member initializer that specifies a collection initializer after the equals sign is an initialization of an embedded collection. Instead of assigning a new collection to the field or property, the elements given in the initializer are added to the collection referenced by the field or property.
所以你的code代码大致相当于:
Foo tmp = new Foo();
tmp.Bar.Add(1);
tmp.Bar.Add(2);
tmp.Bar.Add(3);
tmp.Baz[1].Bar.Add(4); // This will throw KeyNotFoundException if Baz is empty
tmp.Baz[1].Bar.Add(5);
tmp.Baz[1].Bar.Add(6);
Foo f = tmp;
您的初始化版本将抛出 WhosebugException
,因为 Foo
的初始化程序需要创建 Foo
的新实例,而后者需要创建 [=12= 的新实例]等