Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# : Transitive Inheritance

Is Inheritance a transitive relation in C#?

I am asking because I cannot understand why IList<T> implements ICollection<T> and IEnumerable<T> as ICollection<T> already implements IEnumerable<T>

Thanks for clarifying this for me.

like image 268
user388377 Avatar asked Jan 30 '11 23:01

user388377


2 Answers

It is transitive in all regards. Probably the tool that you use to look at the inheritance hierarchy has a certain way of displaying it. There is no way to unimplement an interface although you can implement it explicitly and thereby hide it from intellisense.

As the author of IList you can freely choose to derive from ICollection only or from ICollection and IEnumerable. IEnumerable would be redundant in this case and flagged by resharper.

like image 142
usr Avatar answered Sep 21 '22 08:09

usr


AFAIK, it doesn't truly matter whether you declared IList<T> as:

public interface IList<T> : ICollection<T>, IEnumerable<T> { ... }

or simply as:

public interface IList<T> : ICollection<T> { ... }

Any class that wants to implement IList<T> will have to implement all of these interfaces, i.e. also the inherited ones.

Obviously, if you implemented this interface without implementing the GetEnumerator methods of the IEnumerable/IEnumerable<T> interfaces, you'd get a compiler error; this "proof" by demonstration should be enough to tell you that "interface inheritance" is transitive, indeed.


Sidenote 1. On a side note (and slightly off-topic), consider that you can also do the following:

class Base
{
    public void Foo() { ... }
}

interface IFoo
{
    void Foo();
}

class Derived : Base, IFoo 
{ }

Derived doesn't actually implement IFoo; its base class Base provides method Foo, but doesn't explicitly implement IFoo itself.

This compiles well, seemingly because all the methods that are required by the interfaces are there. (I'll leave it at that and leave the exact technical talk aside for now.)

The reason why I'm mentioning this seemingly unrelated phenomenon is that I like to think of interface inheritance in this way: You need to implement all methods required by the interfaces specified in the class declaration. So when I see

interface ICollection<T> : IEnumerable<T> { ... }

instead of saying, "ICollection<T> inherits IEnumerable<T>", I could say to myself, "ICollection<T> requires of all implementing classes that they implement IEnumerable<T>, also."


Sidenote 2. To conclude this answer with yet another somewhat related anecdote (I promise it'll be the last one):

Some time ago I watched the video Inside .NET Rx and IObservable/IObserver in the BCL on Channel 9. As you might now, those two new interfaces, coming from Rx, were introduced into the BCL with .NET 4. One peculiar thing is that when you subscribe an observer to an observable via observable.Subscribe(observer), all you get back is some anonymous IDisposable. Why?

As the talkers explain in that video, they could have given the IDisposable a more descriptive name (such as ISubscription), via a type name "alias" defined as follows:

interface ISubscription : IDisposable {}

However, they finally decided against this. They figured that once an ISubscription is returned from the Subscribe method, it would no longer be obvious that the returned value needs to be Diposed.

So that's another slightly problematic side of "interface inheritance" that one should keep in mind.

like image 45
stakx - no longer contributing Avatar answered Sep 18 '22 08:09

stakx - no longer contributing