Why does a collection initializer expression require IEnumerable to be implemented?
Why does this generate a compiler error:
class X { public void Add(string str) { Console.WriteLine(str); } }
static class Program
{
static void Main()
{
// error CS1922: Cannot initialize type 'X' with a collection initializer
// because it does not implement 'System.Collections.IEnumerable'
var x = new X { "string" };
}
}
but this doesn’t:
class X : IEnumerable
{
public void Add(string str) { Console.WriteLine(str); }
IEnumerator IEnumerable.GetEnumerator()
{
// Try to blow up horribly!
throw new NotImplementedException();
}
}
static class Program
{
static void Main()
{
// prints “string” and doesn’t throw
var x = new X { "string" };
}
}
What is the 开发者_运维技巧reason for restricting collection initializers — which are syntactic sugar for a call to an Add
method — to classes that implement an interface which doesn’t have an Add
method and which isn’t used?
An object initializer doesn't; a collection initializer does. It's so that it's applied to classes which really represent collections, rather than just arbitrary ones which have an Add
method. I have to admit that every so often I've "implemented" IEnumerable
explicitly, just to allow collection initializers - but thrown a NotImplementedException
from GetEnumerator()
.
Note that early in C# 3's development, collection initializers had to implement ICollection<T>
, but that was found to be too restrictive. Mads Torgersen blogged about this change, and the reason behind requiring IEnumerable
, back in 2006.
精彩评论