Какие интерфейсы реализуют все массивы на С#?

Как новый программист .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;)