Подтвердить что ты не робот

Почему классы коллекций в С# (например, ArrayList) наследуются от нескольких интерфейсов, если один из этих интерфейсов наследует от остальных?

Когда я нажимаю f12 по ключевому слову ArrayList, чтобы перейти к метаданным, сгенерированным с vs2008, я обнаружил, что сгенерированное объявление класса следующим образом

public class ArrayList : IList, ICollection, IEnumerable, ICloneable

Я знаю, что IList уже наследует от ICollection и IEnumerable, поэтому почему ArrayList избыточно наследуется от этих интерфейсов?

4b9b3361

Ответ 1

Хорошо, я провел некоторое исследование. Если вы создаете следующую иерархию:

  public interface One
    {
        void DoIt();
    }

    public interface Two : One
    {
        void DoItMore();
    }

    public class Magic : Two
    { 
        public void DoItMore()
        {
            throw new NotImplementedException();
        }

        public void DoIt()
        {
            throw new NotImplementedException();
        }
    }

И скомпилируйте его, затем обратитесь к DLL в другое решение, введите Magic и нажмите F12, вы получите следующее:

 public class Magic : Two, One
    {
        public Magic();

        public void DoIt();
        public void DoItMore();
    }

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

Обновление. Если вы откроете DLL в ILDASM, вы увидите следующее:

реализует... Два

реализует... Один.

Ответ 2

Дополнительные интерфейсы показаны, потому что они подразумеваются IList. Если вы реализуете IList, вы также должны реализовать ICollection и IEnumerable.

Ответ 3

Я просто догадываюсь, но я думаю, что на самом деле он только реализует IList в коде, но в документации также показаны остальные интерфейсы, чтобы сделать его явным для программиста, использующего класс.

Ответ 4

Из MSDN....

Если класс реализует два интерфейса которые содержат элемент с тем же подписи, а затем член класса будет интерфейсы для использования этого члена в качестве реализация.

Также используется явная реализация разрешить случаи, когда два интерфейса каждый из них объявляет разных членов такое же имя, как свойство и Метод:

Ответ 5

Не принимайте это как ответ.

Я повторяю, что сказал workmad3 выше.

Внедряя его в ArrayList, становится легко узнать, какие интерфейсы ArrayList реализуют, а не то, чтобы перейти к IList, чтобы найти, что он реализует ICollection и IEnumerable.

Это позволяет избежать необходимости возврата назад и вперед цепи наследования.

EDIT: на базовом уровне интерфейс, реализующий другой интерфейс, не может обеспечить реализацию. Полученный класс (от IList), следовательно, косвенно реализует ICollection и IEnumerable. Таким образом, даже если вы пишете собственный класс, реализующий IList (и не добавляя ICollection, IEnumerable в объявление), вы увидите, что он должен будет обеспечить реализацию для ICollection и IEnumerable.

И рассуждение workmad3 имеет смысл.

Ответ 6

Я предполагаю, что CLR не поддерживает интерфейс, который наследуется от другого интерфейса.

Однако С# поддерживает эту конструкцию, но она должна "сгладить" дерево наследования, совместимое с CLR.

[изменить]

После того, как нижеприведённый совет быстро настроит проект VB.Net:

Public Interface IOne
    Sub DoIt()
End Interface

Public Interface ITwo
    Inherits IOne
    Sub DoIt2()
End Interface

Public Class Class1
    Implements ITwo

    Public Sub DoIt() Implements IOne.DoIt
        Throw New NotImplementedException()
    End Sub

    Public Sub DoIt2() Implements ITwo.DoIt2
        Throw New NotImplementedException()
    End Sub
End Class

Компилирование результатов в следующем (С#):

public class Class1 : ITwo
{
    public Class1();
    public void DoIt();
    public void DoIt2();
}

Это показывает, что VB.Net делает НЕ выравнивание иерархии интерфейса в отличие от С#. Я понятия не имею, почему это было бы.