Почему классы коллекций в C# (например, ArrayList) наследуются от нескольких интерфейсов, если один из этих интерфейсов наследуется от остальных?
-
06-07-2019 - |
Вопрос
Когда я нажимаю f12 на ключевом слове ArrayList, чтобы перейти к метаданным, сгенерированным из vs2008, я обнаружил, что сгенерированное объявление класса выглядит следующим образом:
public class ArrayList : IList, ICollection, IEnumerable, ICloneable
Я знаю, что IList уже наследуется от ICollection и IEnumerable, так почему же ArrayList избыточно наследует от этих интерфейсов?
Решение
Хорошо, я провел небольшое исследование. Если вы создаете следующую иерархию:
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, вы увидите следующее:
реализует ... два
реализует ... One.
Другие советы
Дополнительные интерфейсы показаны, потому что они подразумеваются IList. Если вы реализуете IList, вы также должны реализовать ICollection и IEnumerable.
Я просто догадываюсь, но я думаю, что в действительности он реализует только IList в коде, но документация также показывает остальные интерфейсы, чтобы сделать это явным для программиста, использующего класс.
Из MSDN .... р>
Если класс реализует два интерфейса которые содержат член с таким же подпись, а затем реализовать это член в классе будет вызывать как интерфейсы для использования этого члена в качестве их реализация. Р>
Явная реализация также используется разрешить случаи, когда два интерфейса каждый объявляет разных членов такое же имя, как свойство и Метод: р>
Не принимайте это как ответ.
Я повторяю то, что workmad3 сказал выше.
Реализуя его в ArrayList, становится легко узнать - какие интерфейсы реализует ArrayList, а не переходя к IList, чтобы обнаружить, что он реализует ICollection & amp; IEnumerable.
Это избавляет от необходимости возвращаться & amp; вперед цепочка наследования.
РЕДАКТИРОВАТЬ: На базовом уровне интерфейс, реализующий другой интерфейс, не может обеспечить реализацию. Класс, производный (от IList), следовательно, косвенно реализует ICollection & amp; И так же много. Таким образом, даже если вы напишите свой собственный класс, реализующий IList (и не добавите ICollection, IEnumerable в объявлении) - вы увидите, что он должен будет обеспечить реализацию для ICollection & amp; IEnumerable.
И аргументация workmad3 имеет смысл.
Я предполагаю, что CLR не поддерживает интерфейс, унаследованный от другого интерфейса.
Однако C# поддерживает эту конструкцию, но для обеспечения совместимости с 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
Компиляция приводит к следующему (C#):
public class Class1 : ITwo
{
public Class1();
public void DoIt();
public void DoIt2();
}
Это показывает, что VB.Net делает НЕТ сгладить иерархию интерфейсов в отличие от C#.Я понятия не имею, почему это произойдет.