Why does IEnumerableT inherit from IEnumerable?
Straight from the horse's mouth (Hejlsberg):
Ideally all of the generic collection interfaces (e.g.
ICollection<T>
,IList<T>
) would inherit from their non-generic counterparts such that generic interface instances could be used both with generic and non-generic code. For example, it would be convenient if anIList<T>
could be passed to code that expects anIList
.
As it turns out, the only generic interface for which this is possible is
IEnumerable<T>
, because onlyIEnumerable<T>
is contra-variant: InIEnumerable<T>
, the type parameter T is used only in "output" positions (return values) and not in "input" positions (parameters).ICollection<T>
andIList<T>
use T in both input and output positions, and those interfaces are therefore invariant. (As an aside, they would have been contra-variant if T was used only in input positions, but that doesn't really matter here.)
<...snip...>
So, to answer your question, IEnumerable<T>
inherits from IEnumerable
because it can! :-)
Why Enumerable doesn't inherits from IEnumerableT
The Select(), Where() etc are "extension methods". They need to be defined "elsewhere" as an interface can't supply an implementation of methods.
You can recognize extension methods by the keyword "this" in the argument list. For instance:
public static IEnumerable<TSource> Where<TSource>(
this IEnumerable<TSource> source,
Func<TSource, bool> predicate
)
can be used as if it's a method on an IEnumerable<TSource>
with one parameter: Func<TSource, bool> predicate
.
Why IListT inherits IEnumerableT and IEnumerable again
The documentation is generated that way so you can see what interfaces a type implements without having to follow transitive links through the interface inheritance hierarchy.
Inheriting from IEnumerable
You don't inherit from IEnumerable. That is an interface. You can implement interfaces.
The error message you show leads me to suspect that you are implementing IEnumerable.GetEnumerator()
which returns IEnumerator
(a non-generic interface) but attempting to use the generic, IEnumerator<T>
interface in your code.
The code in your link indeed shows the implementation of a generic interface
public IEnumerator <T> GetEnumerator()
{
return Items.GetEnumerator();
}
Why does ICollectionT implement both IEnumerableT and IEnumerable
The non-generic interface is for backward compatibility. If you write code using generics and want to pass your collection to some module written in .NET 1.0 (which doesn't have generics) you still want this to succeed, and you want the old method to be able to iterate through it.
Inheriting IEnumerablestring cause error CS0738
IEnumarable< T> inherits IEnumarable. So you need to implement IEnumerator IEnumerable.GetEnumerator()
method also.
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
Also, your code won't compile, because GetEnumerator
method should return IEnumerator
instead of IEnumarable
. Use GetEnumarator method to get IEnumerator
.
public class TestEnumarable : IEnumerable<string>
{
public IEnumerator<string> GetEnumerator()
{
LinkedList<string> a = new LinkedList<string>();
return a.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
CollectionT: why does it implement both IEnumerable and IEnumerableT?
It says it implements IEnumerable
because it implements IEnumerable
.
IEnumerable<T>
inherits IEnumerable
, but it can obviously provide no implementation. Classes that implement IEnumerable<T>
must also implement IEnumerable
, whether or not they explicitly state that they do so.
class Foo : IEnumerable<T>
class Foo : IEnumerable<T>, IEnumerable
With either case, you implement the members of both interfaces. The second class definition simply makes it obvious for those looking at the class and/or the documentation, which is a good thing. An inexperienced or otherwise uninformed reader might not know that IEnumerable<T>
brings IEnumerable
along with it. They might might not know that a class that implements IEnumerable<T>
can be used where an IEnumerable
is expected. This simply provides a bit more information to the reader, which can only be a good thing on average.
Related Topics
Rotate - Transposing a List<List<String>> Using Linq C#
Login Using Google Oauth 2.0 with C#
Entity Framework Many to Many Through Containing Object
Nsubstitute - Testing for a Specific Linq Expression
How to Get the Available Wifi Aps and Their Signal Strength in .Net
Adding and Removing Anonymous Event Handler
How to Move Rigidbody Gameobject
Post-Increment Within a Self-Assignment
What's the Role of Gethashcode in the Iequalitycomparer<T> in .Net
How to Set Attributes Values Using Reflection
Dbset.Attach(Entity) VS Dbcontext.Entry(Entity).State = Entitystate.Modified
Regular Expression to Allow Backslash in C#