Не так давно мы с Вами рассматривали базовые типы данных в языке программирования C#. Описанные типы, вполне стандарты и присутствую почти по всех языках программирования. Однако по мимо обычного понятия «тип данных» существует понятие «массив определенного типа данных» — именно о них мы и поговорим в данной главе.
Так что же такое массив? Если мы хотим сказать определение массива простыми словами — то, наверное, стоит остановиться на следующем определении. Массив — это набор переменных одного типа, причем данный набор имеет конечное число элементов. У Вас сразу может возникнуть вопрос — а чем этот набор переменных отличается от набора переменных, который можно создать следующим образом:
int var1 = 0, var2 = 1, var3 =2, ... ;
Ответить на данный вопрос очень просто. А самое главное, что ответ на данный вопрос и будет основным наглядным примером того, почему массивы это удобно и зачем их вообще придумали.
Представьте что перед Вами стоит следующая задача: «У Вас есть 5 банок в которые кладут деньги. Вам нужно написать программу, которая будет запрашивать у пользователя ввод цифры — сумму накопленных денег в каждой банке». Как можно решить данную задачу без массивов? В целом решение достаточно простое:
double bottle1 = 0.0, bottle2 = 0.0, bottle3 = 0.0, bottle4 = 0.0, bottle5 = 0.0; Console.WriteLine("Введите сумму средств в банке 1"); bottle1 = Double.Parse(Console.ReadLine()); Console.WriteLine("Введите сумму средств в банке 2"); bottle2 = Double.Parse(Console.ReadLine()); Console.WriteLine("Введите сумму средств в банке 3"); bottle3 = Double.Parse(Console.ReadLine()); Console.WriteLine("Введите сумму средств в банке 4"); bottle4 = Double.Parse(Console.ReadLine()); Console.WriteLine("Введите сумму средств в банке 5"); bottle5 = Double.Parse(Console.ReadLine());
Все просто. Но не кажется ли Вам что слишком громоздко? Лично мне кажется… К тому же, представьте что банок у Вас не 5, а 100 или 1000 или 10000? Сколько времени Вам придется потратить, что бы повторить данный код для такого количества вводов данных? Я боюсь даже представить это.
Именно тут нам на помощь и приходят массивы. Как я уже упоминал выше, массив — это набор данных одного типа.
Общий синтаксис создания массива в C# выглядит следующим образом:
<тип данных>[] <название переменной массива> = new <тип данных>[<размерность массива>];
Таким образом, если мы хотим создать массив m типа int в котором будет 10 элементов, то мы напишем:
int[] m = new int[10];
Теперь вернемся к нашим банкам и решим задачу с применением массива:
int bottleCount = 5; int[] bottles = new int[bottleCount]; for(int i = 0; i < bottles.Length; ++i) { Console.WriteLine("Введите сумму средств в банке {0}", i + 1); bottles[i] = Double.Parse(Console.ReadLine()); }
Как минимум решение стало не такое топорное. Так же стоит отметить, что у нас появляется динамика. В целом нам уже не Важно сколько у нас банок, количество строчек кода это не изменит. Единственное, что нам нужно изменить - это значение переменной bottleCount, и вот у нас уже не 5, а 10000 банок.
Что необходимо знать про массивы в C#? Самое главное, что стоит запомнить и никогда не забыть - это:
- Массив это класс
- Так как это класс, то он передается по ссылке (что это такое можно посмотреть в заметке чем класс отличается от структуры в C#)
- Для доступа к определенной позиции массива используются квадратные скобки []
- Нумерация элементов массива начинается с нуля
Примечание: Если Вам сложно работать с массивами, то для наглядности имейте перед собой листок с ручкой. Представляйте массив в виде набора блоков, которые идут друг за другом.
Теперь давайте представим, что все таки мы яростные противники массивов. И в рамках нашей задачи мы все таки готовы создать 1000 отдельных переменных. Однако вдруг наша задача немного меняется. Теперь банки нам каждый день привозят с завода. При этом их количество может отличаться. Как можно решить данную задачу будучи противником массивов? Ответ никак. Мы не имеем возможности создавать динамическое количество переменных. Но вот создать массив динамической длины мы можем. Нам лишь нужно немного изменить первую строчку нашего решения:
Console.WriteLine("Введите количество банок:"); int bottleCount = Int32.Parse(Console.ReadLine()); int[] bottles = new int[bottleCount]; for(int i = 0; i < bottles.Length; ++i) { Console.WriteLine("Введите сумму средств в банке {0}", i + 1); bottles[i] = Double.Parse(Console.ReadLine()); }
Описанный выше пример очень Важен. Код подобного рода встречается в реальных задачах часто. Именно он позволяет делать Ваше приложение гибким и универсальным, а так же организовать хранение большого количества данных.
Теперь перейдет ко второй части нашей темы - строки. На самом деле тут все очень просто. Давайте подумаем логически. Что такое строка? Строка - это набор символов. В одном определении мы видим два знакомых нам слова "символ" и "набор". Символ - это тип данных (char), а набор - это массив. Таким образом строка, по сути - это массив типа char. А значит мы можем работать с ней, как с массивом и получать доступ к определенным символам, например:
string myString = "Hello!"; Console.Write(myString[1] + myString[4] + myString[5]); //Выведет "eo!"
Однако не забываем, что массив - это класс. А если мы говорим о классе string - то мы говорим об очень мощном классе в котором реализовано огромное количество операций. По мимо этого класс string имеет одно очень важное ограничение - мы не можем заменить отдельно стоящий символ в строке (хотя изменить отдельно стоящий элемент массива Вы можем):
int[] m = new int[2]; m[0] = 1; //ok m[1] = 2; //ok m[0] = 0; //ok string s = "hello"; s[0] = 'H'; //error
Большое количество встроенных функций и совершенно иная логика работы строк в C#, создают полное впечатление, что тип string это совсем не массив, а нечто отдельное. Возможно так оно и есть, но здравый смысл и обычный перенос понятия строк в реальную жизнь - все же подсказывает, что строки - это набор символов, а соответственно массив типа char.