tags:

views:

89

answers:

5

It struck me as weird that any class that inherits from IEnumerable<T> doesn't need to implement Add(T object), even though if you want to use collection initializers when initializing the class instance, you have to implement Add(T object).

Why this is so?

A: 

Because IEnumerable<T> is an interface for enumerating a collection, nothing else.

From MSDN:

Exposes the enumerator, which supports a simple iteration over a collection of a specified type.

Winston Smith
+5  A: 

IEnumerable<T> is a read-only interface - it's only meant to represent "a sequence".

Collection initializers require Add in order to work, but they check that the type implements IEnumerable first to make sure it really is a collection type of some description. They don't require the generic form as that would be restrictive for some pre-2.0 code (in particular various UI collections don't implement IEnumerable<T> IIRC) and they don't require a specific Add signature as collection initializers can be used with different numbers of arguments. For example, Dictionary<TKey, TValue> has Add(TKey value, TValue value) so you can use:

var dictionary = new Dictionary<string, int>
{
    { "Jon", 33 },
    { "Tom", 6 }
};

That means it can't be restricted to (say) IList which only has the single-argumnet Add method. It needs duck typing to some extent, but the IEnumerable requirement is an attempt to make sure that Add really means "add an item to the collection" rather than something completely different. The compiler doesn't use the fact that it implements IEnumerable - it never calls GetEnumerator when building the collection, for example.

Jon Skeet
Straight from the horse's mouth here: http://blogs.msdn.com/madst/archive/2006/10/10/What-is-a-collection_3F00_.aspx
LukeH
It's worth noting that `foreach` does use duck typing on `IEnumerable`, so it is possible to iterate over something using `foreach` without being able to use collection initializers on it.
thecoop
A: 

IEnumerable is the bottom of the pile when it comes to "lists" it has the bare basics needed to enumerate over the list, which makes it read only functions.

Matthew Hood
A: 

I guess the biggest reason is that not all collections have to be Enumerable. Also, the fact that you could have other items that are enumerable that are say calculations or some other process.

For example you could use IEnumerable with a Yield command to calculate out prime numbers or the fibonacci sequence. It's really up to you.

As to the collection initializers since you are working with a collection I am assuming that maybe the initializers are using something akin to the Yield command so it uses IEnumerable to yield up your initialized values to the Add method.

My two cents.

Joshua Cauble
A more compelling reason is that not all enumerables need to be collections.
erikkallen
+2  A: 

As others have stated, IEnumerable is a read-only interface indicating that a sequence can be iterated, nothing more.

Your wider question about why collection initialisers require the combination of IEnumerable and an Add method is probably best addressed by Mads Torgersen:

What is a collection?

What did we find then? Only 14 of our own (public) classes (with public constructors) implement ICollection<T>! Obviously there are a lot more collections in the framework, so it was clear that we needed some other way of telling whether something is a collection class. LINQ to the rescue once more: With modified versions of the query it was easy to establish that among our public classes with public constructors there are:

  • 189 that have a public Add method and implement System.Collections.IEnumerable

  • 42 that have a public Add method but do not implement System.Collections.IEnumerable

If you look at the classes returned by these two queries, you realize that there are essentially two fundamentally different meanings of the name “Add”:

a) Insert the argument into a collection, or

b) Return the arithmetic sum of the argument and the receiver.

People are actually very good at (directly or indirectly) implementing the nongeneric IEnumerable interface when writing collection classes, so that turns out to be a pretty reliable indicator of whether an Add method is the first or the second kind. Thus for our purposes the operational answer to the headline question becomes:

A collection is a type that implements IEnumerable and has a public Add method

LukeH