9. Массивы и коллекции. Индексаторы.
Массивы
Одномерные
Массивы являются коллекциями объектов одного типа. Поскольку длина массивов практически не ограничена, они могут использоваться для хранения тысяч или даже миллионов объектов, но размер массива должен быть указан при его создании. Каждый элемент массива доступен по числовому индексу, указывающему позицию или ячейку, в которой объект хранится в массиве. Массивы могут хранить как ссылочные типы, так и типы значений. Одномерные массивы
Массив является индексированной коллекцией объектов. Одномерный массив объектов объявляется следующим образом.
type[] arrayName;
Часто элементы в массиве инициализируются в это же время, как показано ниже.
int[] array = new int[5];
string[] days = {"Sun", "Mon", "Tue", "Wed", "Thr", "Fri", "Sat"};
System.Console.WriteLine(days[0]); // Выводит "Sun"
Многомерные
Многомерные массивы
Концептуально, многомерный массив с двумя измерениями напоминает сетку. Многомерный массив с тремя измерениями напоминает куб.
// Двумерный массив
int[,] array2D = new int[2,3];
// Инициализация двумерного массива
int[,] array2D2 = { {1, 2, 3}, {4, 5, 6} };
// Запись элементов
for (int i=0; i<2; i++)
{
for (int j=0; j<3; j++)
{
array2D[i,j] = (i + 1) * (j + 1);
}
}
// Чтение элементов
for (int i=0; i<2; i++)
{
for (int j=0; j<3; j++)
{
System.Console.Write(array2D[i,j]);
}
System.Console.WriteLine();
}
Массивы массивов
Одним из вариантов многомерного массива является массив массивов. Массив массивов представляет собой одномерный массив, в котором каждый элемент является массивом. Элементы массива не обязаны иметь одинаковый размер.
Объявить массив массивов можно следующим образом
int[][] jaggedArray = new int[3][];
jaggedArray[0] = new int[5];
jaggedArray[1] = new int[4];
jaggedArray[2] = new int[2];
Использование оператора foreach
Оператор foreach часто используется для доступа к каждому элементу, хранимому в массиве.
int[] numbers = { 4, 5, 6, 1, 2, 3, -2, -1, 0 };
foreach (int i in numbers)
{
System.Console.Write("{0} ", i);
}
Коллекции
Массив является одним из многочисленных вариантов хранения набора данных, используемых C#. Вариант выбора зависит от нескольких факторов, например от планируемого способа управления или доступа к элементам. Например, список работает, как правило, быстрее массива при добавлении элемента в начало или в середину коллекции. Другие типы классов коллекций, такие как хэш-таблица, связный список и стек, имеют свои преимущества. Дополнительные сведения см. в разделах System.Collections и System.Collections.Generic.
В следующем примере показано использование класса List
public class TestCollections
{
public static void TestList()
{
System.Collections.Generic.List<string> sandwich = new System.Collections.Generic.List<string>();
sandwich.Add("bacon");
sandwich.Add("tomato");
sandwich.Insert(1, "lettuce");
foreach (string ingredient in sandwich)
{
System.Console.WriteLine(ingredient);
}
}
}
Индексаторы
Индексаторы являются синтаксическим удобством, позволяющим создавать класс, структуру или интерфейс, доступ к которому клиентские приложения получают, как к массиву. Чаще всего индексаторы реализуются в типах, главная цель которых — инкапсуляция внутренней коллекции или массива. Например, предположим, что имеется класс с именем "TempRecord", представляющий набор температур по шкале Фаренгейта, полученных в 10 различных моментов в течение 24 часов. Класс содержит массив с именем "temps" типа "float", представляющий температуры, и System.DateTime, представляющий дату регистрации температур. Путем внедрения в этот класс индексатора клиенты получат доступ к температурам в экземпляре TempRecord с помощью float temp = tr[4], а не float temp = tr.temps[4]. Использование индексатора не только упрощает синтаксис для клиентских приложений, но и делает класс и его назначение интуитивно понятными для других разработчиков.
Чтобы объявить индексатор для класса или структуры, используйте ключевое слово this как показано в следующем примере:
public int this[int index] Объявление индексатора
{
// объявление геттеров и сеттеров
}
Пример индексатора
class TempRecord
{
// Массив температур
private float[] temps = new float[10] { 56.2F, 56.7F, 56.5F, 56.9F, 58.8F,
61.3F, 65.9F, 62.1F, 59.2F, 57.5F };
public int Length
{
get { return temps.Length; }
}
// Объявление индексатора
public float this[int index]
{
get
{
return temps[index];
}
set
{
temps[index] = value;
}
}
}
class MainClass
{
static void Main()
{
TempRecord tempRecord = new TempRecord();
// Использование индексатора (сеттер)
tempRecord[3] = 58.3F;
tempRecord[5] = 60.1F;
// Использование индексатора (геттер)
for (int i = 0; i < 10; i++)
{
System.Console.WriteLine("Element #{0} = {1}", i, tempRecord[i]);
}
}
}