为什么我可以将集合初始化程序与其他类的私有集访问一起使用?

请考虑以下代码:

public sealed class Order { public Order() { Items = new List(); } public List Items { get; private set; } } public sealed class OrderItem { } 

这是另一个类中的Order初始化。

 var order = new Order { Items = { new OrderItem(), new OrderItem() } }; 

你能解释一下它的工作原理吗? 如您所见Order具有private set属性,所以我认为不可能设置它的值。

简短回答:

它通过集合初始化程序工作 ,它调用Add来添加项目

答案很长:

适当的C#3.0 cpesification,实现IEnumerable对象和具有适当的Add方法可以通过Add方法初始化。

Itemspublic get accessor, ItemsList ,它实现了IEnumerable并且有Add 。 以下是编译器查看代码的方式

 var order = new Order(); order.Items.Add(new OrderItem()); order.Items.Add(new OrderItem()); 

请注意,编译器不使用List实现IEnumerable ,这里是certificate,不会抛出任何exception

 public sealed class Order { public Order() { Items = new MyCollection(); } public MyCollection Items { get; private set; } } public sealed class OrderItem { } public class MyCollection : IEnumerable { private readonly List _items = new List(); public void Add(OrderItem item) { _items.Add(item); } public IEnumerator GetEnumerator() { throw new NotImplementedException(); } } 

来自C#语言规范

应用集合初始值设定项的集合对象必须是实现System.Collections.IEnumerable的类型,否则会发生编译时错误。 对于按顺序的每个指定元素,集合初始值设定项在目标对象上调用Add方法,并将元素初始值设定项的表达式列表作为参数列表,为每个调用应用正常的重载决策。 因此,集合对象必须包含每个元素初始值设定项的适用Add方法。

您的语句有效,因为集合初始化语法使用Add()方法将项添加到集合中,而不是将成员设置为集合的新实例。 从本质上讲,您的代码相当于:

 var order = new Order(); order.Items.Add(new OrderItem()); order.Items.Add(new OrderItem()); 

这很好,因为你只使用了getter方法。