Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does IList<T> implement IEnumerable<T> and ICollection<T> while ICollection<T> itself implements IEnumerable<T> [duplicate]

Why is IList defined like this?

public interface IList<T> : ICollection<T>, IEnumerable<T>, IEnumerable

public interface ICollection<T> : IEnumerable<T>, IEnumerable

public interface IEnumerable<T> : IEnumerable

Couldn't it just be

public interface IList<T> : ICollection<T>

So, to test I created these interfaces, just to be sure if that works!

public interface IOne
{
    string One();
}

public interface ITwo : IOne
{
    string Two();
}

public interface IThree : ITwo, IOne
{
    string Three();
}

While its perfectly fine, Resharper complains about "Redundant interfaces".

Any ideas why Microsoft went on with this implementation?

like image 702
now he who must not be named. Avatar asked Mar 20 '15 06:03

now he who must not be named.


People also ask

What is the difference between ICollection and IList?

An IList extends ICollection. An IList can perform all operations combined from IEnumerable and ICollection, and some more operations like inserting or removing an element in the middle of a list.

Should I use ICollection or IEnumerable?

IEnumerable contains only GetEnumerator() method, like read-only iterate. ICollection is one step ahead of IEnumerable. If we want some more functionality like Add or remove element, then it is better to go with ICollection because we cannot achieve that with IEnumerable. ICollection extends IEnumerable.

Should I return IEnumerable or ICollection?

If you do not counting in your external code it is always better to return IEnumerable, because later you can change your implementation (without external code impact), for example, for yield iterator logic and conserve memory resources (very good language feature by the way).

Does list t implement IEnumerable?

List implements IEnumerable, but represents the entire collection in memory. LINQ expressions return an enumeration, and by default the expression executes when you iterate through it using a foreach, but you can force it to iterate sooner using .


1 Answers

Interface "inheritance" is one of the most misleading terms in software engineering. You didn't inherit squat, interfaces don't have any implementation so you can't inherit it either. You only inherit the demand to implement the methods.

Adding to that demand by repeating the interface declaration doesn't change anything, you already had the demand and adding an extra demand makes no difference whatsoever. So since it doesn't matter, Microsoft helpfully just repeats the interface so you can tell in one fell swoop what interfaces are implemented by, say, List. You don't have to drill down to the interface declaration to see that List implements IEnumerable as well. It is a self-documenting coding style, recommended.

Do beware of the other side of this medal, two distinct interfaces with the exact same method can be implemented with just a single method implementation. While that is often useful, sometimes that is not what you want. Say, ICowboy and IPainter, they both have a Draw() method. It should not do the same thing :) You then have to fall back to an explicit implementation to avoid the ambiguity.

Addressing the Resharper complaint, it isn't very helpful of course. Resharper tends to assume the worst from a programmer. But if you want to shut it up then you need to remove IOne from the IThree inheritance list, it is redundant. Same thing for the class that implements IThree, you'd also need to remove ITwo and IOne from the inheritance list. Or just turn off the warning.

like image 51
Hans Passant Avatar answered Sep 20 '22 19:09

Hans Passant