Why can I use a collection initializer with private set access from another class?

.net, c#

Solution

Short answer:

It works thru collection initializer which calls `Add` to add items

Long answer:

Accodingly C# 3.0 cpesification, object which implement `IEnumerable` and has appropiate `Add` method can be initialised thru the `Add` method.

`Items` has `public get` accessor and `Items` it's a `List<T>` which implements `IEnumerable` and has `Add`. Here's how the compiler sees your code

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

Please note, the compiler doesn't use info that the `List` implements `IEnumerable`, here's the proof, no exception will be thrown

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

from C# Language Specification

The collection object to which a collection initializer is applied must be of a type that implements `System.Collections.IEnumerable` or a compile-time error occurs. For each specified element in order, the collection initializer invokes an Add method on the target object with the expression list of the element initializer as argument list, applying normal overload resolution for each invocation. Thus, the collection object must contain an applicable `Add` method for each element initializer.

Problem

Consider the following code: ``` public sealed class Order { public Order() { Items = new List<OrderItem>(); } public List<OrderItem> Items { get; private set; } } public sealed class OrderItem { } ``` and here's `Order` initialization in another class. ``` var order = new Order { Items = { new OrderItem(), new OrderItem() } }; ``` Could you explain why it works? As you see the `Order` has `private set` property, so I thought it would be impossible to set its value.

Original source