C #: переходное наследование - PullRequest
11 голосов
/ 31 января 2011

Является ли Inheritance переходным отношением в C #?

Я спрашиваю, потому что не могу понять, почему IList<T> реализует ICollection<T> и IEnumerable<T>, поскольку ICollection<T> уже реализует IEnumerable<T>

Спасибо за разъяснение этого для меня.

Ответы [ 2 ]

8 голосов
/ 31 января 2011

Это транзитивно во всех отношениях.Вероятно, инструмент, который вы используете для просмотра иерархии наследования, имеет определенный способ его отображения.Невозможно реализовать интерфейс, хотя вы можете реализовать его явно и, таким образом, скрыть его от intellisense.

Как автор IList, вы можете свободно выбирать только из ICollection или из ICollection и IEnumerable.В этом случае IEnumerable будет избыточным и помечен как resharper.

4 голосов
/ 31 января 2011

AFAIK, действительно не имеет значения, объявили ли вы IList<T> как:

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

или просто как:

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

Любой класс, который хочет реализовать IList<T>придется реализовать всех этих интерфейсов, то есть также наследуемых.

Очевидно, что если вы реализовали этот интерфейс без реализации GetEnumerator методов IEnumerable / IEnumerable<T>интерфейсы, вы получите ошибку компилятора;этого «доказательства» демонстрацией должно быть достаточно, чтобы сказать вам, что «наследование интерфейса» действительно транзитивно.


Sidenote 1. На заметку (и немного не по теме)), учтите, что вы также можете сделать следующее:

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

interface IFoo
{
    void Foo();
}

class Derived : Base, IFoo 
{ }

Derived на самом деле не реализует IFoo;его базовый класс Base предоставляет метод Foo, но явно не реализует сам IFoo.

Это компилируется хорошо, по-видимому, потому что все методы, которые требуются интерфейсами, есть.(Я оставлю это на этом и оставлю пока точный технический разговор.)

Причина, по которой я упоминаю этот, казалось бы, не связанный феномен, заключается в том, что мне нравится думать о наследовании интерфейса следующим образом:необходимо реализовать все методы, требуемые интерфейсами, указанными в объявлении класса.Поэтому, когда я вижу

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

вместо того, чтобы сказать, "ICollection<T> наследует IEnumerable<T>" , я могу сказать себе: "ICollection<T> требует от всех реализацииклассы, которые они реализуют IEnumerable<T>, также. "


Sidenote 2. В завершение этого ответа еще одним несколько связанным анекдотом (обещаю, что это будетпоследний):

Некоторое время назад я смотрел видео Внутри .NET Rx и IObservable / IObserver в BCL на 9 канале. Как выВозможно, теперь эти два новых интерфейса, начиная с Rx , были введены в BCL с .NET 4. Одна особенность состоит в том, что когда вы подписываете наблюдателя на наблюдаемое через observable.Subscribe(observer), все, что вы получаетеэто какой-то аноним IDisposable.Почему?

Как говорят в этом видео говорящие, они могли бы дать IDisposable более описательное имя (например, ISubscription) через имя типа "псевдоним", определенное следующим образом:

interface ISubscription : IDisposable {}

Однако они наконец решили против этого.Они полагали, что после возврата ISubscription из метода Subscribe больше не будет очевидно, что возвращаемое значение должно быть Dipose d.

Так что это еще одна слегка проблематичная сторона интерфейсанаследство ", что следует иметь в виду.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...