Массивы

Массивы в C# представляют собой ссылочные объекты. Память для них выделяется в пространстве кучи, а не в стеке. Способ хранения элементов массива определяется их типом. Если элемент относится к ссылочному типу (например, string), в массиве сохраняются ссылки на них. Если элемент относится к структурному типу (например, число или тип struct), то элементы сохраняются непосредственно в массиве. Другими словами, массив структурных типов не содержит упакованных экземпляров.

Синтаксис объявления массивов выглядит так:

<тип>[] <идентификатор>;

Изначально ссылка на массив равна null. Объект массива создается оператором new:

int[] store = new int[50];

string[] names = new string[50];

Только что созданный массив заполняется значениями по умолчанию, соответствующими типу хранящихся в нем элементов. Так, каждый элемент массива store представляет собой число типа int, равное 0. В массиве names каждый элемент относится к типу string и равен null.

Инициализация массива

Массивы можно инициализировать в момент создания. При инициализации конструкцию new int[x] указывать не обязательно — компилятор автоматически вычислит размер массива по количеству элементов в списке инициализации:

int[] store = {0, 1, 2, 3, 10, 12};

Приведенная строка эквивалентна следующей:

int[] store = new int[6] {0, 1, 2, 3, 10, 12};

Многомерные и ступенчатые массивы

Для индексации элементов в нескольких направлениях используются многомерные и ступенчатые (jagged) массивы.

Многомерные массивы

Многомерные массивы объявляются с несколькими измерениями:

int[,] matrix = new int[4,2];

matrix[0, 0] = 5;

matrix[3, 1] = 10;

Массив matrix является двумерным. В первом измерении его размер равен 4, а во втором — 2. Инициализация этого массива может быть выполнена следующей командой:

int[,] matrix = {{1, 1}, {2, 2}, {3, 5}, {4, 5}};

Многомерные массивы иногда называют «прямоугольными массивами», поскольку их элементы можно представить в виде прямоугольной таблицы (если размерность массива равна 2). При выделении памяти для массива matrix в куче выделяется один блок, в котором хранятся все элементы массива (рис. 16.1).

<16-01>

Рис. 16.1. Хранение данных в многомерном массиве

Ступенчатые массивы

Ступенчатый массив представляет собой «массив массивов». Он называется ступенчатым, поскольку количество элементов по каждому измерению не является постоянной величиной. Рассмотрим пример:

int[][] matrix = new int[3][];

matrix[0] = new int[10];

matrix[1] = new int[11];

matrix[2] = new int[2];

matrix[0][3] = 4;

matrix[1][1] = 8;

matrix[2][0] = 5;

Одномерный массив matrix состоит из 3 элементов, каждый из которых представляет собой целочисленный массив. Первый элемент-массив содержит 10 чисел типа int, второй — 11 чисел, и третий — всего 2 числа.

Поскольку каждый элемент ступенчатого массива также является массивом, при инициализации каждому элементу массива верхнего уровня присваивается null. Таким образом, каждый элемент также необходимо инициализировать массивом. По этой причине не существует обобщенного синтаксиса инициализации ступенчатых массивов. Впрочем, в «псевдо-двумерном» случае приведенный выше фрагмент можно записать следующим образом:

int[][] matrix = {new int[5], new int[4], new int[2]};

matrix[0][3] = 4;

matrix[1][1] = 8;

matrix[2][0] = 5;

 

Массивы ссылочных типов

Массивы, содержащие элементы ссылочного типа, иногда становятся причиной недоразумений, поскольку элементы массива инициализируются величиной null вместо значения, определяемого типом элемента. Например:

class Employee

{

public void LoadFromDatabase(int employeeID)

{

// Загрузка данных из базы

}

}

class Test

{

public static void Main()

{

Employee[] emps = new Employee[3];

emps[0].LoadFromDatabase(15);

emps[1].LoadFromDatabase(35);

emps[2].LoadFromDatabase(255);

}

}

При вызове LoadFromDatabase() инициируется исключение, поскольку значения элементов массива еще не были заданы и поэтому остаются равными null.

Этот класс можно привести к следующему виду:

class Employee

{

public static Employee LoadFromDatabase(int employeeID)

{

Employee emp = new Employee();

// Загрузка данных из базы

return(emp);

}

}

class Test

{

public static void Main()

{

Employee[] emps = new Employee[3];

emps[0] = Employee.LoadFromDatabase(15);

emps[1] = Employee.LoadFromDatabase(35);

emps[2] = Employee.LoadFromDatabase(255);

}

}

В этом варианте мы создаем экземпляр и загружаем в него данные, после чего сохраняем его в массиве.

Инициализация массивов не выполняется из соображений быстродействия. Если бы компилятор инициализировал массивы, ему пришлось бы выполнять одни и те же действия для каждого элемента массива. Если бы эта инициализация оказалась ненужной, то все затраты по выделению памяти оказались бы напрасными.

Предлагаю ознакомиться с аналогичными статьями: