Tuesday, April 05, 2011

So many interfaces!

Today, another question from StackOverflow, and again, presented as a dialogue as is my wont.
The MSDN documentation for List<T> says that the class is declared as

public class List<T> : IList<T>, ICollection<T>, IEnumerable<T>, 
                       IList, ICollection, IEnumerable

Does List<T> really implement all those interfaces?
Yes.

Why so many interfaces?

Because when an interface like IList<T> inherits from an interface like IEnumerable<T> then implementers of the more derived interface are required to also implement the less derived interface. That's what interface inheritance means; if you fulfill the contract of the more derived type then you are required to also fulfill the contract of the less derived type.

So a class or struct is required to implement all the methods of all the interfaces in the transitive closure of its base interfaces?
Exactly.

Is a class (or struct) that implements a more-derived interface also required to state in its base type list that it is implementing all of those less-derived interfaces?
No.

Is the class required to not state it?
No.

So it's optional whether the less-derived implemented interfaces are stated in the base type list?
Yes.

Always?
Almost always:
interface I1 {}
interface I2 : I1 {}
interface I3 : I2 {}

It is optional whether I3 states that it inherits from I1.
class B : I3 {}
Implementers of I3 are required to implement I2 and I1, but they are not required to state explicitly that they are doing so. It's optional.
class D : B {}
Derived classes are not required to re-state that they implement an interface from their base class, but are permitted to do so. (This case is special; see below for more details.)
class C<T> where T : I3
{
  public virtual void M<U>() where U : I3 {}
}
Type arguments corresponding to T and U are required to implement I2 and I1, but it is optional for the constraints on T or U to state that.
It is always optional to re-state any base interface in a partial class:
partial class E : I3 {}
partial class E {}
The second half of E is permitted to state that it implements I3 or I2 or I1, but not required to do so.
OK, I get it; it's optional. Why would anyone unnecessarily state a base interface?
Perhaps because they believe that doing so makes the code easier to understand and more self-documenting.
Or, perhaps the developer wrote the code as
interface I1 {}
interface I2 {}
interface I3 : I1, I2 {}
and the realized, oh, wait a minute, I2 should inherit from I1. Why should making that edit then require the developer to go back and change the declaration of I3 to not contain explicit mention of I1? I see no reason to force developers to remove redundant information.