为什么我可以使用集合初始化器来访问另一个类的私有集合?

本文关键字:集合 另一个 访问 可以使 我可以 初始化 为什么 | 更新日期: 2023-09-27 18:03:19

考虑以下代码:

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

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

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

你能解释一下它为什么有效吗?如您所见,Order具有private set属性,因此我认为不可能设置其值。

为什么我可以使用集合初始化器来访问另一个类的私有集合?

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

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

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

简短回答:

它通过调用Add的集合初始化器来添加项

长答:

根据c# 3.0规范,实现IEnumerable并具有适当的Add方法的对象可以通过Add方法初始化。

Itemspublic get访问器和Items, List<T>实现了IEnumerable并有Add。以下是编译器如何看待你的代码

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

请注意,编译器不会使用List实现IEnumerable的信息,这是证明,不会抛出异常

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<OrderItem> _items = new List<OrderItem>();
    public void Add(OrderItem item)
    {
        _items.Add(item);
    }
    public IEnumerator GetEnumerator()
    {
        throw new NotImplementedException();
    }
}

应用集合初始化项的集合对象必须是实现System.Collections.IEnumerable或发生编译时错误。对于按顺序指定的每个元素集合初始化器调用目标对象上的Add方法元素初始化式的表达式列表作为参数列表;对每个调用应用正常的重载解析。因此,集合对象必须包含一个适用的Add方法

元素初始值设定项。