Массивы с ненулевой базой и интерфейс
Статья, объясняющая новичку размерности массивов и интерфейсы.
Введение
Массивы представляют собой фиксированное количество элементов конкретного типа, тем самым позволяя рассматривать несколько элементов как единый набор. Массивы в .NET в основном идут с отсчетом от нуля, и все типы массивов неявно унаследованы от абстрактного класса System.Array abstract, который сам унаследован от корневого класса System.Object. Отсюда следует, что массивы всегда являются ссылочными типами, размещаемыми в управляемой куче (в отличие от расположения в ряд в стеке потока в виде последовательности байтов) и что переменное или поле приложения содержит ссылку на массив, а не элементы самого массива. Эта статья делает упор на использование массивов с ненулевой нижней границей. Перед этой темой надо коснуться некоторых основ System.Array. Чтобы объявить и отсортировать массив:
Вывод: 3, 1, 2
Читателю заметна простота этого кода, и многие недоумевают, как он может использоваться практически. Это показано позже. В C# ( и CLR - общеязыковая среда исполнения) массив обозначается квадратными скобками после типа элемента. Например: char[] vowels = new char[5]; Квадратные скобки также индексируют массив, обращаясь к конкретному элементу:
Цикл for – одна управляющая конструкция, проходящая по всем элементам в массиве, следовательно, она обойдет в цикле целое число I от 0 до 4:
Вывод: A, E, I, O, U
Свойство length(длина) массива возвращает количество элементов в массиве. Эти массивы печатают вывод строки буквенно-цифровых символов в виде массива.CLR позволяет создавать и работать с массивами, имеющими ненулевые нижние границы. Чтобы создать динамический массив, можно вызвать статический метод CreateInstance() класса System.Array. Существует несколько перегрузок этого метода, позволяющих задать тип элементов в массиве, количество размерностей в массиве, нижние границы каждой размерности и количество элементов в каждой размерности. Математически, точка на отрезке прямой одномерна. Отрезок прямой двумерен, и геометрический круг или квадрат трехмерен. CreateInstance выделяет память для массива, сохраняет информацию о параметре в части служебных данных блока памяти массива и возвращает ссылку на массив. Код ниже показывает, как динамически создать 2-мерный массив значений System.Decimal. Первая размерность представляет календарные годы с 2008 по 2012. Несмотря на то, что при написании статьи 2010 еще не наступил, использование массива показывает, растет ли доход (в идеале при развитии компании: гипотетический сценарий). Вторая размерность представляет финансовые кварталы с 1 по 4 включительно.
Массивы с ненулевой нижней границей
Производительность доступа к массиву
Как сказано выше, массивы – способ рассматривать несколько элементов как единую коллекцию. Коллекции начинаются там, где массивы кончаются, и стоит надеяться, что новичок сможет дойти до коллекций и обобщений. Но вспомните, что ссылка на сам массив хранится в управляемой куче, а не элементы. Стало быть, доступ к элементам из массива является показателем производительности. Внутри CLR поддерживает два разных вида массивов:• Одномерные массивы с нижней границей 0• Одномерные и многомерные массивы с неизвестной нижней границей
Код ниже сначала покажет, что когда массив имеет два и более размерностей, можно привести ссылку, возвращенную из CreateInstance(), к переменной ElementType[] (где ElementType – имя некоторого типа), что облегчает доступ к элементам в массиве. Если массив имеет одну размерность, то в C# надо использовать методы GetValue и SetValue класса Array для доступа к элементам массива.
Обратите внимание на комментарии, идущие за каждым Console.WriteLine, означающим вывод. Для одномерного массива с отсчетом от нуля отображается имя типа System.String[]. Массив с отсчетом от единицы отображает тип System.String[*]. * сообщает CLR, что это не массив с отсчетом от нуля. Для многомерных массивов Console.WriteLine отображает тип System.String[,]. Ясно, что доступ к элементам одномерного массива с отсчетом от нуля быстрее, чем доступ к элементам массивов с отсчетом не от нуля. Причина этого находится в метаданных и в коде промежуточного языка, генерируемых компилятором CSC.exe. Введя с клавиатуры команду ildasm /metadata=validate /out: Access.il Access.il для типа ‘type Access.il’, можно изучить и проанализировать код промежуточного языка. Возникает мысль, что компилятор C# может вводить в заблуждение. При компиляции создаются лишние объекты, и код должен оптимизироваться с помощью переключателя /optimize+. Предпочтительный инструмент анализа кода - ildasm.exe. Ниже дан фрагмент кода промежуточного языка (без таблиц метаданных):
Есть специальные команды промежуточного языка, такие как newarr, ldelem, ldelema, ldlen, и stelen, используемые для обработки одномерных массивов с отсчетом от нуля. Эти специальные команды промежуточного языка заставляют динамичный компилятор генерировать оптимизированный код.