Fun with IEnumerable and collection initializers
Jaco Jansen van Vuuren
Software DeveloperIEnumerable and collection initializers. You probably use them every day (if you write C# code at least) without thinking about the implementation details too much. And honestly - neither did I. But after I got a null reference exception (by accident, of course) whilst doing an assignment to a collection I was reminded about some of the interesting parts of IEnumerable - and some of the fun stuff you can do with it.
Collection initializers?
Put very simply, collection initializers allow you to turn this:
Into this:
As you can see - the version using the collection initializer is a lot cleaner.
A look under the hood
Let's take a look at the IL that is generated by the C# compiler for the following initializer by running it through dotPeek.
The (shortened by me) IL is below - take a look too see if you can see what is happening.
If you spotted what I wanted you to see you would have noticed that the C# compiler calls the ".Add" method for every string specified in the brackets. That means that the initializer is equivalent to mutliple calls to ".Add".
Below is the IL for the the same method - but using ".Add" instead of the collection initializer:
Different ways to initialize collections on creation
Consider the following class:
Using initializers - you can create a new instance of it like this:
You can also do the following (note the missing new) - but be careful - you will get a runtime NullReferenceException if the list is not instantiated:
To avoid the NullReferenceException you can set a default value for Values in SomeClass. This could also be useful if you always want a value in the list:
So how does the C# compiler know which classes support collection initializers?
Basically - it checks that the class implements IEnumerable. If it does - it can be used with a collection initializer.
Abusing IEnumerable and collection initializers to build an addition calculator
Before we dive into this - I have to warn you. Don't do something like this in production.
Consider the following class:
We can use it as follows:
But what would happen if we implemented IEnumerable on it and used a collection initializer? Would that work?
Here is the same class - but implementing IEnumerable:
Usage - note the use of the collection initializer. The C# compiler will automatically insert all the calls to ".Add" in the IL:
As you can see - by implementing IEnumerable on our class we can "force" the compiler to allow us to use collection initializers instead of typing ".Add" several times.
If you are interested in learning more about collection initializers in C# - I would highly recommend reading C# In Depth which covers initializers and many other topics in great detail.