До настоящего момента мы использовали в программах простые переменные. При этом каждой области памяти, выделенной для хранения одной величины, соответствует свое имя. Если переменных много, программа, предназначенная для их обработки, получается длинной и однообразной. Поэтому в любом процедурном языке есть понятие массива — ограниченной совокупности однотипных величин. Элементы массива имеют одно и то же имя, а различаются порядковым номером (индексом). Это позволяет компактно записывать множество операций с помощью циклов.
Массив относится к ссылочным типам данных, то есть располагается в динамической области памяти, поэтому создание массива начинается с выделения памяти под его элементы. Элементами массива могут быть величины как значимых, так и ссылочных типов (в том числе массивы). Массив значимых типов хранит значения, массив ссылочных типов — ссылки на элементы. Всем элементам при создании массива присваиваются значения по умолчанию: нули для значимых типов и null — для ссылочных.
|
|
На рис. 6.1 представлен массив, состоящий из пяти элементов любого значимого типа, например int или double, а рис. 6.2 иллюстрирует организацию массива из элементов ссылочного типа.
Вот, например, как выглядят операторы создания массива из 10 целых чисел и массива из 100 строк:
int[] w = new int[10];
string[] z = new string[100];
Рис. 6.1. Простые переменные и массив из элементов значимого типа
Рис. 6.2. Массив из элементов ссылочного типа
В первом операторе описан массив w типа int[]. Операция new выделяет память под 10 целых элементов, и они заполняются нулями.
Во втором операторе описан массив z типа string[].Операция new выделяет память под 100 ссылок на строки, и эти ссылки заполняются значением null. Память под сами строки, составляющие массив, не выделяется — это будет необходимо сделать перед заполнением массива.
Количество элементов в массиве (размерность) не является частью его типа, это количество задается при выделении памяти и не может быть изменено впоследствии. Размерность может задаваться не только константой, но и выражением. Результат вычисления этого выражения должен быть неотрицательным, а его тип должен иметь неявное преобразование к int, uint, long или ulong.
Пример размерности массива, заданной выражением:
short n = 25;
string[] z = new string[n + 1];
Элементы массива нумеруются с нуля, поэтому максимальный номер элемента всегда на единицу меньше размерности (например, в описанном выше массиве w элементы имеют индексы от 0 до 9). Для обращения к элементу массива после имени массива указывается номер элемента в квадратных скобках, например:
|
|
w[4] z[i]
С элементом массива можно делать все, что допустимо для переменных того же типа. При работе с массивом автоматически выполняется контроль выхода за его границы: если значение индекса выходит за границы массива, генерируется исключение IndexOutOfRangeException.
Массивы одного типа можно присваивать друг другу1. При этом происходит присваивание ссылок, а не элементов, как и для любого другого объекта ссылочного типа, например:
int[] a = new int[10];
int[] b = а; // b и а указывают на один и тот же массив
Все массивы в С# имеют общий базовый класс Array, определенный в пространстве имен System. В нем есть несколько полезных методов, упрощающих работу с массивами, например методы получения размерности, сортировки и поиска. Мы рассмотрим эти методы немного позже в разделе «Класс System.Array»
ПРИМЕЧАНИЕ--------------------------------------------------------------------------
Массивы, являющиеся полями класса, могут иметь те же спецификаторы, что и поля, представляющие собой простые переменные.
В С# существуют три разновидности массивов: одномерные, прямоугольные и ступенчатые (невыровненные).