Какие интерфейсы реализуют все массивы на С#?
Как новый программист .NET 3.5, я начал изучать LINQ, и я нашел что-то довольно основное, чего я раньше не заметил:
В книге утверждается, что каждый массив реализует IEnumerable<T>
(очевидно, иначе мы не могли бы использовать LINQ для объектов на массивах...). Когда я увидел это, я подумал про себя, что никогда не думал об этом, и я спросил себя, что еще реализуют все массивы - поэтому я исследовал
System.Array
с помощью обозревателя объектов (поскольку это базовый класс для каждого массива в CLR), и, с моей точки зрения, он не реализует IEnumerable<T>
.
Итак, мой вопрос: где определение? Я имею в виду, как я могу точно определить, какие интерфейсы реализуют каждый массив?
Ответы
Ответ 1
Из документации (основное внимание):
[...] класс Array реализует общие интерфейсы System.Collections.Generic.IList<T>
, System.Collections.Generic.ICollection<T>
и System.Collections.Generic.IEnumerable<T>
. Реализации предоставляются массивам во время выполнения и поэтому не видны инструментам сборки документации.
EDIT:, как указывает Jb Evain в своем комментарии, только векторы (одномерные массивы) реализуют общие интерфейсы. Что касается того, почему многомерные массивы не реализуют общие интерфейсы, я не совсем уверен, так как они реализуют не-общие экземпляры (см. Объявление класса ниже).
Класс System.Array
(т.е. каждый массив) также реализует эти не общие интерфейсы:
public abstract class Array : ICloneable, IList, ICollection, IEnumerable, IStructuralComparable, IStructuralEquatable
Ответ 2
Вы можете найти ответ на свой вопрос эмпирически, используя небольшой фрагмент кода:
foreach (var type in (new int[0]).GetType().GetInterfaces())
Console.WriteLine(type);
Запуск приведенного выше фрагмента приведет к следующему выводу (в .NET 4.0
):
System.ICloneable
System.Collections.IList
System.Collections.ICollection
System.Collections.IEnumerable
System.Collections.IStructuralComparable
System.Collections.IStructuralEquatable
System.Collections.Generic.IList'1[System.Int32]
System.Collections.Generic.ICollection'1[System.Int32]
System.Collections.Generic.IEnumerable'1[System.Int32]
('1
означает <T>
)
После .NET 4.5
(.NET Standard 1.0
и более поздних версий) появилось два дополнительных интерфейса:
System.Collections.Generic.IReadOnlyList'1[System.Int32]
System.Collections.Generic.IReadOnlyCollection'1[System.Int32]
Ответ 3
Начиная с .NET 4.5, массивы также реализуют интерфейсы System.Collections.Generic.IReadOnlyList<T>
и System.Collections.Generic.IReadOnlyCollection<T>
.
Таким образом, при использовании .NET 4.5 полный список интерфейсов, реализуемых массивами, получается (полученный с использованием метода, представленного в ответе Хосама Али):
System.Collections.IList
System.Collections.ICollection
System.Collections.IEnumerable
System.Collections.IStructuralComparable
System.Collections.IStructuralEquatable
System.Collections.Generic.IList'1[System.Int32]
System.Collections.Generic.ICollection'1[System.Int32]
System.Collections.Generic.IEnumerable'1[System.Int32]
System.Collections.Generic.IReadOnlyList'1[System.Int32]
System.Collections.Generic.IReadOnlyCollection'1[System.Int32]
Странно, но кажется, что было забыто обновить документацию по MSDN, чтобы упомянуть эти два интерфейса.
Ответ 4
Осторожно на интерфейсах массива, они могут реализовать их, но на самом деле они этого не делают... Посмотрим на следующий код:
var x = new int[] { 1, 2, 3, 4, 5 };
var y = x as IList<int>;
Console.WriteLine("The IList:" + string.Join(",", y));
try
{
y.RemoveAt(1);
}
catch (Exception e)
{
Console.WriteLine(e);
}
Console.WriteLine(string.Join(",", y));
Он производит следующий вывод: результат
Таким образом, синтаксический анализ работает, но поддерживается не все, что правильно с точки зрения сбора фиксированной длины, но совершенно неправильно, если вы действительно верите, что это список. Там идет Лисков принцип от SOLID :(.
Для быстрого тестирования это поможет.
Ответ 5
Я нашел реализацию IList<T>, ICollection<T>, IEnumerable<T>
во вложенном классе SZArrayHelper
массива.
Но я должен предупредить вас - там вы найдете гораздо больше вопросов...
Референция
После этого я получил только один - there_is_no_array;)