If you're using the object initializer syntax without providing any constructor arguments, you don't even have to type the pair of parentheses following the class name. All of this is syntactic sugar which helps improve the readability of your code.

Collection Initializers

When you create a collection, you often want to seed it with some initial data, just like setting property values on a freshly created object:

This list initialization looks a lot cleaner than its much more verbose counterpart. Other collection types can benefit from the collection initializer syntax as well. Consider the following code which creates a string lookup using a Dictionary<TKey, TValue>:

Hey, that already looks a lot nicer. Now let's see why and how this code compiles.

Compiling Collection Initializers

When the C# compiler encounters a collection initializer, it'll replace the shorthand initializer syntax by appropriate method calls to the collection object. For that to succeed, the collection class needs to implement IEnumerable<T> and provide an accessible method named Add. This is a convention built into the compiler, which Eric Lippert briefly mentions in his post Following the pattern:

There are a few places in the C# language where we do this sort of “pattern matching”; we don’t care what the exact type is, just so long as the methods we need are available.

The Add method also needs to have the correct number of parameters. In the first example, we initialize our list with numbers of type long, which is a valid operation because List<long> defines an Add(long item) method. The second example used a Dictionary<string, string> and provided a list of initializers with two values (e.g. "F#" and "functional"). Those two values map to the two parameters of the Add(string key, string value) method.

Custom Collection Initializers

The compiler has no special knowledge about the initialization of certain collection types. That is, there are no checks hardcoded for types like List<T> or Dictionary<TKey, TValue>. It instead relies on the convention of implementing IEnumerable<T> and providing an Add method with a type-compatible signature in the collection class. This is all about duck typing, if you will.

Now, consider this simple struct which represents a point in three-dimensional space:

Which will initialize the list with {5,5} (both words have five letters). As said this example is stupid, but it comes in handy if you have to add stuff to a list and the original list does not provide an add method with the appropriate signature.