Если я понимаю, как вы описывали цепочку наследования интерфейса .NET, значит, вы ошиблись. Это простая ошибка, так как документация так выглядит. IList<T>
только явно наследуется от ICollection<T>
; не наследуется от ICollection<T>
, IEnumerable<T>
и IEnumerable
. Вот фактическое определение из справочного источника:
public interface IList<T> : ICollection<T>
То же самое относится к ICollection<T>
, оно наследуется только от IEnumerable<T>
. Во время компиляции дерево наследования сглаживается и в некотором смысле дедуплицируется для интерфейсов. Таким образом, интерфейс, который наследует ICollection
, не просто наследует этот интерфейс, который, в свою очередь, наследует IEnumerable
. Скорее интерфейс будет наследовать ICollection
и IEnumerable
сам.
Визуальный пример:
IMine : ICollection<T> != IMine : (ICollection<T>:(IEnumerable<T>:IEnumerable))
Вместо этого это выглядит так:
IMine: ICollection<T>, IEnumerable<T>, IEnumerable
Что объясняет, почему вы сделали вывод, что у вас есть.
Что касается реального примера наследования нескольких интерфейсов, посмотрите примеры IQueryable
и IOrderedQueryable
. Фактическое объявление источника этих интерфейсов выглядит следующим образом:
public interface IQueryable<out T> : IEnumerable<T>, IQueryable {}
public interface IOrderedQueryable<out T> : IQueryable<T>, IOrderedQueryable {}
IQueryable
должен иметь контракт, в котором указано, что вы можете выполнять итерации по каждому элементу, а также возможность отличаться от простого IEnumerable
в том смысле, что он один, а не все типы IEnumerable
могут использоваться в IQueryProvider
и статический Queryable
класс.
Еще одна забавная тема в пространстве имен System.Collections.Concurrent
.
public interface IProducerConsumerCollection<T> : IEnumerable<T>, ICollection
Это интересно, потому что он наследует от ICollection
(не универсальный) и IEnumerable<T>
, которые оба наследуются от IEnumerable
. Конечно, это не проблема, но это еще один хороший пример. Если бы IProducerConsumerCollection<T>
наследовал от ICollection<T>
вместо его неуниверсального аналога, я уверен, что он не будет явно наследоваться от IEnumerable<T>
. Он имеет размер, (старый) поведение перечислителя и методы синхронизации, определенные в ICollection
, а также общее поведение перечисления, определенное в IEnumerable<T>
Есть два примера. Я нашел еще кое-что, но, думаю, этого вполне достаточно.