Видео курс C# стартовый. Массивы - видео уроки ITVDN
ITVDN: курсы программирования
Видеокурсы по
программированию

Заказать звонок

Выбери свою IT специальность

Подписка

Заказать звонок

+38 099 757 27 82

Курс C# 5.0 Стартовый (для начинающих)

×

Вы открыли доступ к тесту! Пройти тест

Вы действительно хотите открыть доступ к тестированию по курсу C# 5.0 Стартовый на 40 дней?

ВИДЕОУРОК №9. Массивы в C#

Войдите или зарегестрируйтесь для того чтоб продолжить просмотр бесплатного видео
В данном видео уроке курса "C# стартовый" Вы сможете ознакомиться историей языка C# и платформы .NET. Вы изучите инструменты, которые будете использовать на протяжении всего курса. Этот урок даст Вам общее понимание того, что такое программирование, какие типы программ можно создать с использованием языка C#. Вы узнаете об актуальных технологиях и возможностях платформы Microsoft .NET. На этом уроке Вы создадите первое приложение “Hello world”, которое пишут все программисты, когда начинают осваивать новый язык программирования. Также научитесь создавать простые оконные приложения с пользовательским интерфейсом, узнаете что такое компиляция и отладка.
Читать дальше...
Этот видео урок поможет Вам разобраться с двоичной и шестнадцатеричной системами исчисления. Познакомит Вас с алгоритмами преобразования десятичных чисел в двоичную, шестнадцатиричную системы и обратно. Разобравший, Вы сумеете лучше понять устройство компьютера и будете подготовлены к следующей теме – переменные и типы данных. Вы узнаете, какие простые типы данных есть в языке C# и какой тип данных следует использовать в конкретной ситуации.
Читать дальше...
Этот видео урок показывает, как правильно использовать типы данных при определении переменных. Также на уроке Вы узнаете о константах и как константы используются в приложениях. Так как с основными принципами создания переменных Вы ознакомились на прошлом уроке, в этом уроке больший акцент будет сделан на различные операции, которые можно производить над переменными, а также принципы форматирования строковых переменных.
Читать дальше...
Ни одно приложение не выполняется линейно. Всегда есть различные условия, которые могут повлиять на результат работы приложения. На этом уроке Вы изучите условные операторы, позволяющие разрабатывать алгоритмы, в которых от выбора пользователя или от других условий будет зависеть результат. В этом уроке будут рассмотрены такие условные конструкции языка C# - if/else, switch, тернарный оператор.
Читать дальше...
На этом уроке Вы изучите основы логики и рассмотрите операторы языка C#, которые будут необходимы при разработке программного обеспечения. В этот урок входят примеры использования логических и побитовых операций. Вы рассмотрите конъюнкцию, дизъюнкцию, исключающее «или», отрицание, операторы сдвига и многое другое. На этом уроке Вы получите не просто теорию, а еще и узнаете, в каких ситуациях могут быть применены данные конструкции.
Читать дальше...
Циклические конструкции – то, без чего не обойдется ни одно приложение. В программировании часто встречаются действия, которые необходимо повторить несколько раз. Вряд ли Вы захотите повторять в коде несколько сотен раз одинаковые операции. Для решения задач, которые требуют неоднократного повторения операций, Вам необходимо разобраться с конструкциями, которые будут изучены в этом уроке. Вы узнаете, какие циклы бывают в языке C#, научитесь их запускать и контролировать.
Читать дальше...
Чтобы научится программировать, мало изучить условные и циклические конструкции. Необходимо использовать еще и другие возможности языка C#. В этом уроке Вы рассмотрите очень важный элемент любого приложения – метод. Вы научитесь создавать методы, узнаете, что такое параметры, возвращаемые типы, сможете различать функции и процедуры. Вы изучите весь необходимый материал, чтобы начать дальнейшее освоение более сложных тем, связанных с объектно-ориентированными техниками в программировании.
Читать дальше...
На этом уроке Вы расширите знания, полученные на предыдущем занятии по методам. Вы узнаете, что такое рекурсия и сложная рекурсия. Рассмотрите новые возможности языка C#, связанные с использованием методов – именованные и опциональные параметры. На этом уроке Вы закрепите свои знания и научитесь пользоваться более сложными техниками программирования.
Читать дальше...
Задача большинства приложений сводится к анализу данных и вычислениям, производимым над большими объемами данных. Для того, чтобы в Вашем приложении появилась возможность хранить большое количество однотипных значений, Вам необходимо создать массив. Видео урок обучит Вас не только создавать массивы, но и производить основные операции над массивами. Вы узнаете, как можно использовать циклы при работе с массивами, а также изучите различные типы массивов – одномерные, многомерные, зубчатые.
Читать дальше...
ПОКАЗАТЬ ВСЕ
основные темы, рассматриваемые на уроке
0:00:55
Что такое массив?
0:17:13
Индекс массива
0:18:45
Использование одномерных массивов
0:28:05
Создание одномерных массивов
0:45:45
Двумерные массивы
0:58:25
Использование двумерных массивов
1:06:20
Массивы состоящие из одного элемента
1:08:15
Трехмерные массивы
1:15:50
Использование трехмерных массивов
1:23:45
Четырехмерные массивы
1:28:42
Зубчатые массивы
1:33:40
Использование зубчатых массивов
1:42:40
Ключевое слово params
ПОКАЗАТЬ ВСЕ
Титры видеоурока

Здравствуйте! Тема нашего сегодняшнего урока – Массивы. Изучив материал сегодняшнего занятия мы научимся создавать и использовать массивы. Это такие специальные конструкции C#, с ними мы еще не знакомы. Научимся выполнять перебор элементов массива. Мы разберем такие массивы как одномерные, двухмерные, трехмерные, четырехмерные массивы, как разновидность многомерные массивов, потому что мы можем позволить строить и пяти-, шести-, семи-, полимерные массивы. Также разберем еще одну интересную разновидность массивов – это зубчатые массивы или Jagged Arrays. И мы с вами переходим к первому слайде презентации. И давайте посмотрим что-же такое массив, что же это за интересное понятие. Обратите внимание, здесь у нас имеется массив знакомых нам байт. Мы понимаем, что когда мы видим такое представление, то мы представляем какой-то участок памяти, то есть ОЗУ. Мы видим, идет набор байтов. Обратите внимание, на вот эти три байта, которые выделены фигурной скобкой. Адрес этого байта 865,865,866. И мы видим, что в этих байтах хранятся некие значения. В этом хранится значение 10 в десятичном. В 16-ричном как оно будет выглядеть? А. И лампочки у нас как будут гореть 0000 1010. Понятно что мы здесь нарисовали, что мы здесь видим вверху то значение, которое хранится в определенном байте. Ниже мы видим некие индексы. Получается, что мы заменяем адрес, этот сложный адрес каждого байта не отдельным человеческим именем, мы заменяем их просто индексами. Мы говорим что к этому байту мы будем обращаться по индексу. К этому по индексу 0. К этому – по индексу 1. К этому – по индексу 2. И обратите внимание, что мы делаем? Мы берем в памяти и выделяем сразу же три байта. И к каждому байту теперь будем обращаться не по имени, а по индексу. Обратите внимание, как, с какого индекса начинается индексация этой области памяти. С нуля. Значит массив представляет собой область памяти в ОЗУ. Что такое массив? Это область памяти, которая разбита условно на некие участки, на отдельные, в данном случае, байты, потому что массив может быть у нас не только байтовый а и с двух байт, ну, мы там посмотрим. Мы видим, что массив – это область памяти, разбита на определенные участки, в данном случае по байтам. Каждый такой участок мы будем называть элементом массива. И мы видим что вот этот элемент имеет индекс 0, вот этот – 1, этот – 2. Обратите внимание, у нас теперь у каждого элемента, у каждого байта. У нас есть только индекс, но вся вот эта область, которую мы нарисовали, будет иметь имя. Представьте что мы вот эту область именуем array. И согласно этого имени, мы сможем обращаться к этой области и после этого нам нужно будет просто указать индекс. Имя самой области, то есть мы понимаем что вот это область памяти с выделенными элементами называется массивом. У целого массива есть имя. У отдельного элемента имени нет, у него есть только индекс. Мы видим что все элементы массива индексируются, то есть имеют свой индекс. Не смотря на то что адрес этого байта 864, логически мы будем обращаться к нему через имя, потом ставить квадратные скобки, ставить некий индекс и закрывать скобку. Вот так мы будем обращаться к отдельном элементы массива. И получается, что мы в нашей программе можем создавать много переменных отдельных. Так же мы можем создавать много массивов. Много вот таких условный переменных. Но мы их не будем называть переменными, мы их будем их называть элементами. Хотя ведут они себя так же как и настоящая переменная, просто у элементов массива нет имени, а есть индекс. Почему так сделано? Для удобства? А где же это удобство? Подождите. Сейчас мы к этому подойдем. Давайте мы посмотрим как мы можем вообще зарезервировать в памяти, как мы можем выделить в памяти область их трех байтов. Ну для этого нам нужно написать имя, как мы хотим назвать эту область. Мы понимает, что если мы выделяем некую область, то мы должны присвоит ей имя. Данная область условно будет называться Array. Вот мы и пишем Array но для того , чтобы нам сказать, что это будет массив. Что это будет область, а не одна переменная, потому что стоит нам зачеркнуть эти скобочки – это будет просто переменная типа byte. Так вот, для того чтобы нам сказать что это массив, нам нужно использовать, во-первых это тип элементов. Мы говорим, что мы хотим выделить область, в которой будут хранится однобайтовые элементы. Вот у нас один элемент, второй элемент… И для этого мы должны указать вот эти квадратные скобки. Значит еще раз смотрим на синтаксис выделения памяти для массива. Синтаксис создания массива. Мы указываем тип элементов в массиве, указываем, что это будет сам по себе массив, указываем имя массива, ставим знак присвоения. Далее мы ставим ключевое слово new. Давайте об этом поговорим. Смотрите, для работы нашей программы требуется две разновидности области памяти. Что это значит? Дело в том, что при выполнении память разделается структурно на две таких важных разновидности памяти: это стек, мы уже знаем что такое стек – это область памяти в ОЗУ для хранения адресов возврата для процедур. Так вот другая область памяти называется куча. Вот на куче как рас располагаются все важные, главные, я бы сказал живые объекты нашей программы. Так вот массивы и представляют собой вот такие большие полноценные объекты, которые будут располагаться в куче. Вот в этой специальной области памяти. И для того чтобы нам сказать, что мы хотим, чтобы наш массив был расположен именно на этой области памяти, на куче. МЫ и должны использовать ключевое слово new. Но в данном случае я хочу сказать, что это синтаксический сахар. Синтаксический сахар – это те элементы языка, которые нужны человеку, но они абсолютно не нужны машине. Посмотрите, для того чтобы наша речь была красивой, мелодичной, мы используем какие-то вспомогательные слова для связки слов, ну, например. Как-то пытаемся что-то уточнить лишний раз, повторить. Так же и здесь, чтобы человеку легко было читать программы мы вот имеет=м тоже в некоторых случаях такие ключевые слова языка, без который вообще-то можно было бы обойтись, но язык был бы сухой и нашему взгляду не за что было бы зацепится и приходилось бы долго вникать в код программы. Мы будем пока считать, что ключевое слово new выполняет следующую роль – оно просит у ОС, говорит: «Выдели мне пожалуйста область памяти на куче и в этой области памяти будет размещаться наш массив.» Но нам пока без разницы где он будет находится. То ли он будет на куче, то ли он будет вообще в космосе. Нам без разницы. Нас интересует просто устройство массива, способы его создания и варианты использования. Ну, мы просто запомним, что мы будем писать это ключевое слово new при создании массива, но не всегда. Дальше, мы повторяется, пишем еще раз байт, мы как бы подтверждаем, что наш массив будет состоять из однобайтовых элементов. Эта область, которую мы указали дальше, мы говорим, что мы хотим создать массив из трех элементов, их трех каких? Однобайтовых элементов. Еще раз, на этой строке мы создаем массив с именем Array. На этой строке мы создаем массив элементов размерностью 3 элемента с именем array. Мы помним, что это имя не есть имя каждого отдельного элемента – это имя всей совокупности этих элементов. Какой можно пример массива привести? У всех были краски акварельные. Смотрите, коробочка с красками. Что на ней написано? Краски. Подождите, а почему на коробке не написано Красный цвет? А как можно там написать Красный цвет, если там еще есть синий, зеленый… Каждый элемент массива – это по сути каждая краска, каждый баллончик, емкость с краской, которая лежала в этой коробочке. И получается, что сам массив – это коробка с красками, а каждый элемент – это отдельный флакончик с краской. Еще раз, мы создаем массив элементов типа byte размерностью в три элемента. Имя массива – array. Мы создаем массив элементов типа byte размерностью в три элемента. Имя массива – array. Хорошо. А давайте мы теперь посмотрим как выглядит массив в программном коде. Давайте посмотрим. Перейдем в студию и смотрим.

   1:  using System;
   2:   
   3:  // Массивы (одномерный массив).
   4:   
   5:  namespace Arrays
   6:  {
   7:      class Program
   8:      {
   9:          static void Main()
  10:          {
  11:   
  12:              // На 14 строке создаем массив целочисленных элементов с именем array размерностью в 5 элементов
  13:   
  14:              int[] array = new int[5];
  15:   
  16:              // На 18 строке элементу массива array по индексу 0 присваиваем значение 10
  17:   
  18:              array[0] = 10;
  19:              array[1] = 20;
  20:              array[2] = 30;
  21:              array[3] = 40;
  22:              array[4] = 50;
  23:   
  24:              // На 26 строке выводим на экран значение элемента массива array по индексу 0
  25:   
  26:              Console.WriteLine(array[0]);
  27:              Console.WriteLine(array[1]);
  28:              Console.WriteLine(array[2]);
  29:              Console.WriteLine(array[3]);
  30:              Console.WriteLine(array[4]);
  31:   
  32:              // Delay.
  33:              Console.ReadKey();
  34:          }
  35:      }
  36:  }

На 14 строке мы создаем массив целочисленных элементов размерностью в 5 элементов. Видите синтаксис создания. Его нужно просто запомнить. Вы скажете, что int размерностью в 4 байта. Хорошо. Это если бы у нас был просто однобайтовый массив. Давайте пока заменим, давайте заменим на byte, посмотрим как у нас будет работать с байтом. Что здесь нужно сделать? Тоже написать byte, видите красным подчеркнуло. Ага, мы создаем массив элементов типа byte с именем array с размерностью 5 элементов. Обратите внимание, на 18 строке мы обращаемся к нулевому элементу массива. Мы помним, что все массивы имеют имя. Все элементы массива имеют индексы. У нас здесь 5 элементов. Но нумеруем мы элементы с нуля. Смотрите, в нулевой элемент мы записываем 10, во второй 20, 30, 40, 50. То есть, вот таким образом мы можем обращаться к каждому отдельному элементу массива и в него что-то записывать. Вот видите, я беру здесь и во второй элемент массива записываю число 555. Просто? Простою Мы видим способ заполнения массива какими-то значениями. А как мы можем обратится на чтение. Как мы можем прочитать и вывести на экран. А вот пожалуйста. Мы выводим на экран значение нулевого элемента массива, далее значение первого элемента массива. То есть получается, что у нас на экран выведется что? 10, 20… То есть мы у видим на экране 10, 20, 30, 40, 50. Смотрите, как просто работать с массивами. То есть, получается, что массив – это набор неких элементов определенного типа, в данном случае byte, вот с которым мы можем работать таким способом. Ага, так не очевидно, зачем же мы так работаем. Проще насоздавать переменных. Но подождите, не спешите, мы сейчас подойдем к преимуществам работы с массивами. Сначала мы посмотри технологически как же с ними работать, а потом мы посмотрим на полезность их использования. Давайте вернемся к нашей презентации вспомним. Значит мы видим, что массив – это некая область памяти, которую мы выделаем. Эта область памяти состоит из определенного количества элементов, которые мы указали при создании. Далее, сама область памяти имеет свое имя, а каждый элемент, который входит в эту область памяти имеет просто индекс, и уже по этому индексу мы и будем обращаться как на запись, так и на чтение к каждому отдельному элементу. Давайте перейдем на следующий слайд. Что нам показывает этот слайд? Мы создаем массив размерностью в 3 элемента. Имя массива array обратите внимание, у нас имеется в этом массиве три элемента. У массива имеется имя – это целая область. Массив – это целая область. Как называется эта большая область? Array. Сколько в ней хранится элементов? 3. Какое значение у первого элемента? У первого элемента пока ноль. А у четвертого? А четвертого элемента здесь нет. Хорошо. Это у нас идут индексы и здесь у нас идет пример использования, пример обращения к нулевому элементу массива. После того как мы выполним эту команду, а мы уже помним, у нас и вроде такое встречалось. Array[0] = 10. То есть здесь появляется 10. Хорошо. Идем дальше. И теперь еще раз синтаксис создания массива в языке C#. Мы должны указать тип элементов массива, квадратные скобки, которые указывают на то, что эта переменная Array будет указывать именно на массив, она будет содержать в себе ссылку на целый массив. То есть, представьте, что это переменная и она выглядит примерно вот так в ООП. Возьмём ее выделим еще раз. А мы выделяем этот массив. Представьте что здесь у нас идет такая веревочка, которая держится за вот этот большой ящик. Но не за каждый отдельный элемент. Для того чтобы нам, видите, это такая ссылочка, которая держится за него, для того, чтобы на м обратится к каждому отдельному элементу массива мы обращаемся по индексу. И мы видим что эта переменная array содержит в себе некую ссылку, которая как раз есть адрес этой области памяти, где на куче. Куча – это специальная область памяти, где у нас и создаются все важные объекты. И вот одним из каких важных объектов может являться массив, который будет состоять так из свих элементов. Но это позже, это на следующем курсе мы будем говорить о таких областях памяти как управляемая и неуправляемая куча, которая принадлежит операционной системе, а вот эта куча принадлежит платформе .NET. Мы же с вами программисты дотнетчики. Правда? Хорошо. Переходим еще раз к описанию синтаксиса. Значит далее мы указываем имя массива, то есть по сути имя массива представляет собой имя переменной, которая ссылается на сам массив. Далее само выражение создания массива. Ключевое слово new – создать на куче – heap – куча – это такое важное понятие. Далее мы еще один раз указываем тип элементов массива, как бы подтверждая что у нас массив элементов типа byte. И в квадратных скобках указываем количество элементов массива, сколько в этой большой области памяти будет выделено элементов – 3. А мы идем дальше на следующий слайд, и смотрим еще раз. Здесь у нас имеется небольшая программка. Здесь мы создаем массив элементов типа byte размерностью в три элемента. Смотрите, ниже мы нулевому элементу присваиваем значение 10, первому – 20, третьему – 30. Но мы помним, что массивы индексируются с нуля. И даже авторы делали книжки, которые описывали язык С, у них была нулевая глава, первая, вторая, чтобы программисты могли запомнить, что все массивы индексируются с нуля. Хотя есть языки у которых массивы искусственно индексируются с 1. Смотрим дальше. А что мы здесь делаем? Мы выводи на экран значение каждого элемента массива. Здесь мы выводим на экран, обратите внимание, значение элемента массива по индексу 0. Видите, вот оно. Вот мы его вывели на экран. Далее по индексу 1, вот оно 20. Ну и так далее. И три – 30. Последнего элемента вывели. Думаю, что здесь достаточно просто. Правда? А мы переходим к следующему слайду. Обратите внимание, мы уже говорили, что элементы массива могут быть не только однобайтовыми, но и двухбайтовыми, и четырех байтовыми. И в нашем программном коде мы видели, что на 14 строке мы создаем массив элементов типа int. То есть каждый элемент будет размером в 4 байта и размерность в 5 элементов. И какая же общая длина в байтах массива? 4*5 = 20. 20 байт будет общая размерность этого массива. Перейдем в презентацию. Значит здесь мы имеем область памяти, обратите внимание, мы создаем массив элементов типа short размерность в 3 элемента. Это значит, что у нас выделится область памяти, такого размера, смотрите, short сколько занимает? 2. Сколько нам нужно элементов по 2 байта? 3. И вот получается, что мы здесь создаем три… Раз, два, три. Три двухбайтовых элемента. И снова же видим их индексы. 0, 1, 2. Значит мы видим, что мы создаем массив элементов типа short размерность в 3 элемента. Здесь же мы в нулевой элемент записали 10, в первый – 20, во второй – 30. И далее выводим значения элементов массива на экран. Вот мы вывели их на экран. Давайте вернемся теперь в студию и посмотрим. Обратите внимание, на 14 строке мы создаем массив целочисленных элементов с именем array с размерность в 5 элементов. Мы понимаем, что что у нас здесь будет? Здесь будет раз, два, три, четыре. Первый элемент. Здесь раз, два, три, четыре. Индекс этого 0, следующего 1. И последний элемент рисуем. А какой у него индекс будет? 4. Нулевой, первый, второй, третий четвертый, и каждый элемент такого массива будет 4 байта. А как же такое происходит? Как же машина может вот так определить что тут надо один байт, второй. Как тут все запутанно. За всем этим стоит специальный алгоритм, раньше программисты на ассемблере сами учитывали размер каждого элемента. Сдвигали, делали специальные сдвиги при обращении к каждому элементу. А сегодня здесь просто нужно взять увеличительное стекло и смотреть вот туда внутрь, как же это сделано. То есть современные программисты даже не задумываются о тех сложностях, о которых задумывались низкоуровневые программисты про формировании даже таких простейших массивов. Как раньше сложно было работать с массивами. Сегодня все эти моменты контролируют специальные механизмы позволяя современному программисту не задумываться о таких технических деталях. Нам просто нужно запомнить синтаксис, написать по всем правилам строку, что мы хотим создать массив целочисленных элементов с именем array с размерностью в 5 элементов. И Дальше присвоить определенному элементу с определённым индексов определенное значение. Значит видим, что мы создали массив целочисленных элементов с именем array с размерностью в 5 элементов. Заполнили его значениями, и вывели их на экран. Вывели значение каждого элемента на экран. Выполняемся и смотрим. Обратите внимание, вот мы увидели на экране значение всех элементов массива. А мы идем дальше. Заходим в презентацию и переходим на следующий слайд. Обратите внимание, на этом слайде у нас представлены 4 возможные способа создания массивов. Их имеется 4. Первый мы с вами уже рассмотрели. Второй способ – практически то же самое. Заметьте, один в один как в первом способе только мы после вот этой конструкции указываем блок в операторных скобках. Этот блок в скобках при создании массива называется блок инициализатора. Не инициализации, а блок инициализатор. Где мы сразу же указываем те значения, которые мы хоти присвоить элементам массива. Массив их трех элементов, вот мы и по нулевому индексу записываем 1, по первому – 2, по второму – 3. Это аналогично тому, что мы делали вот здесь. Только мы использовали блок инициализатора. Более того, обратите внимание, если мы пользуемся блоком инициализатора, мы здесь можем даже не писать выделяемую или желаемую размерность массива. Получается, что среда разработки, она сама почитает сколько вы здесь поместили в блоке инициализатора значений и сама подставит нужное значение. И вот последний способ, самый простой. Мы используем только блок инициализатора, даже не пишем всех вот этих реверансов. Не пишем new byte и т.д. Не пишем. Не всегда есть возможность пользоваться массивами с использованием блока инициализатора, потому что если массив у нас большой, например на 100000 элементов, то вряд ли кто-то из Вас захочет заполнять эти элементы вручную, Вы захотите процесс автоматизировать, чтобы машина как-то сама заполнила, чтоб она сама обратилась к каждому элементу. А что я рисую? Я рисую какие-то итерации, какие-то циклические действия. Точно! Возможно, мы с массивами можем работать вместе с циклами. Хорошо. А мы переходим к нашему программному коду и смотрим. Дальше, заходим во второй пример и смотрим. Точно! Мы здесь уже видим циклы, цикл for. Как он называется? Цикл со счетчиком.

   1:  using System;
   2:   
   3:  // Массивы (одномерный массив).
   4:   
   5:  namespace Arrays
   6:  {
   7:      class Program
   8:      {
   9:          static void Main()
  10:          {
  11:              int[] array = new int[5];
  12:   
  13:              // Заполнение массива.
  14:              for (int i = 0; i < array.Length; i++)
  15:              {
  16:                  array[i] = i * 2;
  17:              }
  18:   
  19:              // Вывод на экран значений элементов массива.
  20:              for (int i = 0; i < array.Length; i++)
  21:              {
  22:                  Console.WriteLine(array[i]);
  23:              }
  24:   
  25:              // Delay.
  26:              Console.ReadKey();
  27:          }
  28:      }
  29:  }

На 11 строке мы создаем массив целочисленных элементов с именем array размерностью в 5 элементов. Далее, на 14 строке мы создаем циклическую конструкцию for размерность…А сколько? Обратите внимание! У массивов есть такое важное свойство, как length – длина. Скажите что ж это за свойство? Чему же оно может быть равно? Скорее всего размерности массива. Давайте проверим. Давайте поставим точку останова. Сделаем F5. Так. Остановились и наведем теперь. Смотрите, length равно чему? 5-ти. Индекс у нас чему равен? 0. Вот теперь самое интересное! Мы сейчас в этом цикле for начнем заполнять массив некими значениями. Давайте. Смотрим. Пошагаем, да? Традиционно. F11. Смотрим. Так. Так. Смотрим. I меньше. Length чему равно? 5. 0<5 – true. Входим. Входим в тело цикла. Смотрите, что мы делаем. Давайте наведем на этот массив, посмотрим, что в нем. Мы можем его даже развернуть. Смотрите. Раз. Можем развернуть. Можем его даже закрепить вот здесь. Можем развернуть. Смотрите. Вы видите, что у нас происходит? Мы видим чему равен каждый элемент массива. Пока они чему равны? 0. Шагаем, шагаем дальше. Так. У нас 0 умножить на 2 чему будет равно? 0. И значит мы по нулевому элементу записали что? 0 так и остался. Ладно, шагаем дальше. F11. 0 увеличиваем на 1. Чему i равно? 1. 1<5? Меньше. Входим в тело цикла. Что мы сейчас делаем? Мы сейчас в первый элемент массива. Смотрите. Вот сюда. Видите? Вот сюда. Мы сейчас что запишем? Вы скажете 1 умножить на 2. Мы сюда запишем 2-ку сейчас, да? Смотрите, смотрите, что мы можем делать. Видите, да? Мы сейчас сюда запишем 2-ку. Проверим сейчас? Проверим. F11. Выполнили эту команду. Так. Смотрите. Уже записана 2-ка. А что у нас на следующей итерации произойдет? Так. I равна, по своей величине, 2-м. Так. Здесь 2 умножить на 2 – 4-ре. Это значит, мы по 2-му индексу. Вот сюда мы запишем сейчас что? Что вы говорите? 4? Смотрим. Выполнились 4-ре. Следующее у нас будет… Так. i равно 2. Сейчас мы его увеличим. Чему оно будет равно? 3, да? 3. Смотрите, 3. 3<5 – входим. Так, 3 умножить на 2, сколько? 6. Что мы ожидаем получить по 3-му индексу? 6. Давайте проверим! Смотрите. У нас здесь 6. И последний… Так. I чему у нас сейчас? 3. Сейчас 4<5. Что мы ожидаем? Сейчас вот здесь? Подскажите мне, пожалуйста. Вы скажите, так как i равно 4-м. Мы 4 множим на 2 получается сколько? 8. Давайте проверим точно ли. Обратите внимание! Мы в цикле for взяли и заполнили массив некоторыми значениями по определенному алгоритму. Хотя здесь мы их брали, индекс умножали на 2 и вот получили массив с такими заполненными значениями. Видите, да? Давайте закроем его. Так. Снимаем break point. Нам он здесь больше не нужен. А что делает следующий цикл for? Какая у него размерность? 5. 5 итераций будет произведено. И что мы здесь будем выводить из этого массива? А мы выведем значения элементов массива на экран. Давайте прошагаем. Смотрите. Мы сейчас выводим элемент массива по индексу 0, видите? Что у нас выведется? 0 на экране. Смотрите, вот он уже появился, видите? 0. Еще раз шагаем. Что мы вывели на экран? 2. 2, потому что и равно чему? Давайте сейчас посмотрим. I равно чему? 1. Что у нас по первому индексу? 2. Обратите внимание! Первый цикл позволяет проинициализировать каждый элемент массива каким-то новым значением, а второй цикл, что у нас делает? Выводит на экран значение каждого элемента массива. Давайте остановим нашу программу и сделаем маленькое, маленькое сравнение. Откроем вот эту программу, которую мы рассматривали до. И смотрите, то что нам казалось некрасивым, объемным и неудобоваримым оказывается, что в связке с циклом. Смотрите, видите? Оно оказывается даже элегантным. А теперь представьте, что я попрошу вас здесь сделать вот так. Заполните мне пожалуйста 5000 элементов. Смотрите, 5000 элементов, что вам придется делать? Напрямую, да? Создавать каждый, обращаться. Конечно ж мы так не будем делать, да? А здесь, если я поставлю 5000 элементов и выполню. Смотрите, F5. Смотрите. Вы видите? Быстренько машина мне все пересчитала. Представляете сколько бы мы возились руками, если бы мы работали с переменными, если б у нас не было таких удобных циклических конструкций. А мы свами идем дальше. Открываем следующий пример. Смотрим. А что мы здесь видим? Вы скажете, Александр, мы здесь видим вот что: еще один способ создания массивов, да? Точно. Точно, спасибо, что напомнили.

   1:  using System;
   2:   
   3:  // Массивы (одномерный массив).
   4:   
   5:  namespace Arrays
   6:  {
   7:      class Program
   8:      {
   9:          static void Main()
  10:          {
  11:              // На 14 строке создаем массив целочисленных элементов с именем array размерностью в 5 элементов
  12:              // в блоке инициализатора заполняем его значениями 1,2,3,4,5
  13:              
  14:              int[] array = new int[5] { 1, 2, 3, 4, 5 };
  15:                          
  16:              // Вывод на экран значений элементов массива.
  17:              for (int i = 0; i < array.Length; i++)
  18:              {
  19:                  Console.WriteLine(array[i]);
  20:              }
  21:   
  22:              // Delay.
  23:              Console.ReadKey();
  24:          }
  25:      }
  26:  }

На 14 строке мы создаем массив элементов размерностью в 5 элементов и в блоке инициализатора заполняем этот массив значениями. Видите, да? Но такое возможно только для маленьких массивов, потому что, если я сделаю вот такой массив в 5000 элементов, да? Смотрите. И выполнюсь, у меня получается что? Ошибка. Смотрите. Не получается. Видите, да? Видим, да? То есть блок инициализатора он может быть применим для небольших массивов, для каких-то частных случаев, но для больших массивов, как мы уже с вами говорили, такая конструкция будет абсолютно не применима. А на 17 строке в цикле for, что мы делаем? Так, здесь у нас length будет чему равно? Напомните пожалуйста. Чему? 5? Точно, 5. Все, спасибо. Мы выводим на экран значение каждого элемента массива, то есть, сто у меня здесь будет? Скажете: 1, 2, 3, 4, 5. Давайте здесь поставим break point. Выполнимся, F5. Дойдем до сюда, кликнем по нашему массиву, развернем. Смотрите, видите? Вот. Вот все элементы массива, которые мы заполнили в блоке инициализатора. Давайте переходим к следующему примеру. Что здесь у нас имеется? А здесь у нас имеется 3-тий вариант. Обратите внимание, где мы не указываем размерность массива вообще. Система сама определяет, да? Эту размерность. Она сама определяет. Сама не явно для нас подставляет. Интересно, точно ли она ее может определить, да? Давайте начнем шагать. Наведем на length. Смотрите. Она сама посчитала 1, 2, 3, 4, 5 и в свойства length подставила вот эту 5-ку, то есть размер элементов. А ну подождите! Давайте мы изменим добавим еще, например, 2 элемента, да? Добавим 6-ой и 7-ой. И снова же нажмем F11 и посмотрим чему равно? 7-ми. Видите? Система сама определяет размерность массива. Снова же здесь мы рассмотрели использование блока… Как он называется? Блок инициализатора. Но снова же мы помним, что блок инициализатора можно использовать только на коротких массивах. Кому сколько не лень, скажем так. Кому сколько не лень заполнять. Я думаю, что когда вы уже заполните там элементов 20, допустим 25 вы уже скажете – нет надо мне задуматься над тем, чтобы как-то автоматизировать инициализацию элементов массива, потому что… Понимаете, сегодня 25, а потом меня нечистая сила заставит заполнять 100, 125, 1125, а это что? Это не очень красиво, да? Другие программисты скажут – нет, он совсем не умеет работать с массивами, да? Поэтому мы не будем лишний аз использовать вот такие подходы. Заходим в 5-тый. Смотрим.

   1:  using System;
   2:   
   3:  // Массивы (одномерный массив).
   4:   
   5:  namespace Arrays
   6:  {
   7:      class Program
   8:      {
   9:          static void Main()
  10:          {
  11:              int[] array = { 1, 2, 3, 4, 5 };
  12:   
  13:   
  14:              // Вывод на экран значений элементов массива.
  15:              for (int i = 0; i < array.Length; i++)
  16:              {
  17:                  Console.WriteLine(array[i]);
  18:              }
  19:   
  20:              // Delay.
  21:              Console.ReadKey();
  22:          }
  23:      }
  24:  }

А здесь у нас последний вариант. Видите? Когда мы вообще не используем вот такую конструкцию, система и так понимает, что мы создаем массив, она видит, что здесь чистенький блок инициализатора и самостоятельно все рассчитывает, выделяет память в нужном месте, все делает автоматически за нас. Видите какой прекрасный язык C#. Тот же самый пример.

   1:  using System;
   2:   
   3:  // Массивы (одномерный массив).
   4:   
   5:  namespace Arrays
   6:  {
   7:      class Program
   8:      {
   9:          static void Main()
  10:          {
  11:              int[] array = new int[] { 1, 2, 3, 4, 5 };
  12:   
  13:   
  14:              // Вывод на экран значений элементов массива.
  15:              for (int i = 0; i < array.Length; i++)
  16:              {
  17:                  Console.WriteLine(array[i]);
  18:              }
  19:   
  20:              // Delay.
  21:              Console.ReadKey();
  22:          }
  23:      }
  24:  }

Интересно, length чему будет, чему? 7-ми? Давайте проверим. Давайте пошагаем. Можно посмотреть. Так, array. Ага, смотрите 5-ть элементов. Length чему у нас равно? Давайте наведем. 5. Length равно 5-ти. Вспомнили. Замечательно! Свойства length: оно содержит в себе количество элементов в массиве. Запомните: не последний индекс последнего элемента, а количество. Вот так взяли от одного, пересчитали и указали. Мы переходим с вами дальше. Смотрим.

   1:  using System;
   2:   
   3:  // Массивы (одномерный массив).
   4:   
   5:  namespace Arrays
   6:  {
   7:      class Program
   8:      {
   9:          static void Main()
  10:          {
  11:              int[] array = new int[5];
  12:   
  13:             
  14:              // Вывод на экран значений элементов массива.
  15:              for (int i = 0; i < array.Length; i++)
  16:              {
  17:                  Console.WriteLine(array[i]);
  18:              }
  19:   
  20:              // Delay.
  21:              Console.ReadKey();
  22:          }
  23:      }
  24:  }

Еще раз: на 11 строке мы создаем массив целочисленных элементов с именем array размерностью в 5 элементов. Смотрите. Мы здесь в них ничего не записывали, мы не инициализировали их, но питаемся вывести. Как вы думаете получится у нас? Программисты, которые смотрят не начинающие это видео скажут: конечно же получится. Почему? Давайте пошагаем. Я не помню, честно. Давайте пошагаем. Я сам вместе с вами не помню. Нам нужно исследовать, мы ж делаем постоянно discovery и exploration. Так. Наводим. Ага, смотрите здесь записаны только одни нули. Значит, значение по умолчанию для типа int и для каждого отдельного элемента массива это 0, если мы ничего не запишем здесь будут сплошные нули. А length чему у нас будет равно? Length равно 5-ти и если я выполню эту программу уже до конца, что я увижу на экране? 1, 2, 3, 4, 5? Наоборот? Конечно же, нули! Нажимаем F5. Обратите внимание, мы видим, что у нас вывелись одни нули. Поэтому, если мы создаем массив, но ничем не инициализируем его элементы, то что у нас выведется? Нули. А что будет, если мы здесь напишем, например, bool, можно так? Из булевых элементов. Представьте, что мы хотим вот создать массив из результатов высказываний, да? Интересно, как это будет выглядеть. F11. Давайте посмотрим. Так. Смотрите все из false состоит. Вы видите? Все из false. Хорошо. Если мы выполнимся полностью, то мы увидим… Смотрите: false, false, false. Так, а какие у нас там еще были… Давайте char посмотрим. Символы. У них тоже ж, наверно, есть какие-то свои значения по умолчанию – мы с вами уже смотрели. Я просто забыл. Вы помните? Давайте вспомним. Так, F5. Смотрите, пустота. Вы видите? Там был слеш 0, помните. А если мы сделаем string на все типы, с которыми мы знакомы, да? Так, string. Если мы сделаем стринговыми, посмотрим. String. Что же здесь у нас… Вы помните? Я не помню. Давай посмотрим. Всегда если, что-то не помните… Вы раз и… Так. Смотрите: nul, nul, nul, nul, nul. Nul – это значит «ничего». Интересно, оно нам выполнит? Что оно нам повыводит на экран? F5. Смотрите, тоже оно нам ничего не вывело. Абсолютно ничего. Это значение по умолчанию. Хорошо. А мы возвращаемся… Поэкспериментируйте с другими типами. То есть этот пример показывает, что если мы массив не проинициализирует ничем, то элементы заполнятся некими значениями по умолчанию для определенного типа: для типа int значения по умолчанию, мы помним, это 0, для типа bool, boolean – это сколько? Какой? False? Замечательно! А мы с вами переходим теперь к следующей разновидности массивов. Это двухмерные массивы. И мы зайдем сразу же в презентацию и посмотрим, посмотрим какие же у нас бывают еще двухмерные массивы или многомерные массивы. Мы уже начнем говорить с вами сейчас о многомерных массивах. Они бывают: двухмерные, трехмерные, четырехмерные…сколько угодно мерные и вот такие зубчатые, то есть массив состоящий из, так сказать, вот таких тоже подмассивов. И мы переходим к рассмотрению именно двухмерных массивов. Что такое двухмерный массив? Это тоже некая область памяти, разбитая на некие элементы. Видите, да? Здесь, конечно, нам нужно было бы написать не int, а byte. Давайте исправим. Byte. Так, секундочку. Сейчас byte. Вот здесь мы тоже напишем byte, чтобы было… Обратите внимание! Здесь мы создаем двухмерный массив байтовых элементов размерностью 3 на 3. Двухмерные массивы нам напоминают простые матрицы. Вот, например, 3 на 3 мы видим, что? Матрица 3-го порядка: 3 строки, 3 столбца. Просто. Синтаксис создания двухмерного массива тоже простой: мы пишем тип элементов массива, далее мы указываем тип массива. Смотрите, тип массива. Если мы укажем вот так – одномерный массив, вот так – двухмерный массив. Смотрите. Раз, два. Дальше, трехмерный массив, четырехмерных массив, пяти-, шести-, семи-, восьми-, девяти-, десяти-, одиннадцати-, двенадцати-, тринадцати-, четырнадцати-… Что это значит? Вы представляете себе четырнадцати мерное пространство? Нет, мне представить сложно такое. Давайте вернемся к этому. И получается, что мы выделяем область памяти для хранения, условно, вот такой виртуальной конструкции. А что, смотрим, значит, эта область памяти, состоящая из байтиков. Те же самые байты, но обратите внимание на их индексы. Смотрите. Нулевая строка, нулевой столбец. Смотрите, видите? Первая строка, нулевой столбец. Смотрите, это у нас идет нулевой столбец, как в матрице: первый, второй столбец. Здесь мы видим: нулевая строка, первая строка, вторая строка. А что такое матрица? Помните, как в linear algebra – линейная алгебра? Может быть кто-то учил. Это что? Это таблица чисел, просто таблица чисел, которая разбита на строки и столбцы, только там у нас шла нумерация не с нуля, а с одного, да? Если бы мы взяли линейную алгебру, математику, то вот здесь было бы 1, 1, да? Так как мы занимаемся программированием, то мы будем нумеровать все с нуля, потому что мы помним, что все массивы индексируются с нуля. Смотрим. Видите, да? Нулевая, первая, вторая строка, видите? Пошла вторая строка… Хорошо. Значит, мы видим: для того, чтобы нам выделить область памяти для хранения некой матрицы чисел размерностью 3 на 3 нам нужно вот использовать такой синтаксис. Значит, как правильно читается: мы создаем двухмерный массив элементов типа byte с именем array размерностью 3 на 3 (3 строки, 3 столбца) условно. Просто? Просто. Вы скажете мне: Саша, память, память она линейная, как же в ней происходят вот такие выделения? Мы ж не можем ОЗУ представить себе двухмерное, это ж от одного и до миллиардов, просто, как цепочка идет, да? Так, точно. Вы правы. Давайте посмотрим, одним глазом, как же происходит, в таком случае, выделение памяти. Это тоже интересно. Это низко уровневый подход. Высокоуровневому программисту достаточно вот такого понимания, что вот ну выделилась такая матрица, но мы то с вами любопытные, мы хотим посмотреть, да? Значит, смотрим. Снова же, наша область памяти, видите вот идут наши физические адреса – те таблички, которые прикручены к каждому байту, но мы с ними не работаем, почему? Это не удобно. Это здесь они, в начале, такие коротки, а далее они будут длинные и сложные. Хорошо. Смотрим. Смотрите, вот сюда вот-вот-вот… Так, это мне помогает программа lingvo переводить. Смотрим, что мы здесь делаем: мы создаем двухмерный массив элементов типа byte с именем array размерностью 2 на 2 – условно 2 строки, 2 столбца. Как они будут представлены в памяти? А очень просто. Смотрите. Вы видите мы выделили 4-ре байта, условно, их теперь разделили. Смотрите, так сказать, на некие два подмассива. Видите, да? У этого индекс ноль, можно сказать, что это нулевая строка, да? А у этого индекс – один, а у этого первая строка. Мы их можем друг под другом подставить, правда? Как мы смотрели вот в этом примере до этого, видите? Вот они. Мы их могли бы просто взять вот так выставить в ряд. Вот скажите, а кто же их вот так группирует вот таблицы? Специальные программы, которые обслуживают нас в сеансе работы Visual Studio, когда мы программируем, то в сеансе программирования нас еще обслуживает куча различные механизмов, создавая нам иллюзию того, что в вычислительной машине происходит все так как в жизни. Благодаря вот этим иллюзиям очень много, так сказать, не программистов, по специальности, становятся программистами, потому что, если б такой иллюзии не было нам приходилось бы работать вот с такими сложными адресациями, представлениями и самим писать некий модуль, такой специальный модуль, который бы имитировал бы и обслуживал бы вот такую линейную конструкцию и представлял нам ее, например, двухмерно или трехмерно. Представляете, да? Те, кто изучали ассемблер, работали на нем, они обязательно такое делали на своих практикумах. Хорошо. Значит, мы видим, что нулевая строка у нас идет первая, дальше идет – вторая строка. Это вот видите, да? Нулевая, первая строка… Вот видите, как они… Это индексы строк. А вот это что? Индексы столбцов. И теперь, если мы вот так условно вот эту строку поставим под эту строку, то у нас сформируются некие столбцы. Вы представляете себе, да? Вот эти все индексы там, вот вторые индексы столбцов, нужна какая-то программа, которая бы все это подставляла бы туда. Вот. Ужасно, правда? Ужасно. Это все равно, что у нас были бы сейчас только одномерные массивы я бы сказал бы вам: а напишите мне функцию имитации работы с двухмерным массивом. Представляете, да? У нас нет двухмерных массивов. Уже одномерные массивы вы знаете, как создавать методы вы знаете. Я говорю: создайте мне, пожалуйста, возьмите одномерный массив, линейный, создайте мне функцию и позвольте мне работать с этой функцией так как будто бы это, допустим, вот двухмерный массив. Представляете, какие бы запутанные алгоритмы вы писали бы? Это на языке C#. А представляете какие они запутанные на языке ассемблера. Это мы просто с вами посмотрели одним глазом как в действительности, в правде выглядит двухмерный массив, потому что физически двухмерных массивов нет. Понятие двухмерного массива – это просто удобная иллюзия для высокоуровневого программиста. Мне нравится это. Я люблю язык C#. Смотрим, мы создаем двухмерный массив элементов типа byte размерностью 2 на 2. 2 строки на 2 столбца. Первая строка, вторая строка. В первой строке 2 байта, во второй строке 2 байта. Матрица 2х2. Матрица второго порядка. Смотрите, для того, чтобы мне записать какое-то значение в матрицу, то есть в двухмерный массив, мне нужно что? Чтобы вот сюда записать в серединку, что мне нужно? Мне нужно по имени обратится к этому массиву и в квадратных скобочках написать 1, 1. Как это будет выглядеть давайте я вам сейчас напишу при помощи этой программки Марка Русиновича, которой мы делаем презентации. Смотрим, как бы я сюда что-то записал. Array[1,1] = 13. И после того как мы это записали, то что произошло здесь? Здесь загорелись лампочки. Так, и мы сюда записали число 13. Вот 13. Пожалуйста. Как его прочитать вы понимаете, пишем CW Tab+Tab пишем ту же конструкцию и выводим на экран значение числа 13. Просто? Просто. Но единственное важно, просто себе помните, что двухмерные массивы – это всего лишь удобная иллюзия для программиста, это, я так называю, абстракция. На самом деле это некое абстрактное представление, но на самом деле выглядит все линейно. Но вы как высокоуровневые программисты уже никогда больше не столкнетесь вот с таким линейным преставлением массива. Это история. Сейчас же все обслуживается удобно и красиво. Мы видим, что мы здесь создали массив элементов типа byte размерностью 2 на 2 и заполняем его соответствующими значениями. Видите? По индексу 0,0 мы записали 10, 0,1 – 20, 1,0 – 30, 1,1 – 40. И, я думаю, что вам уже такие представления не удобны, такое удобней, потому что мы привыкли работать с матрицами, и нам удобней к ним обращаться. А здесь мне приходится в голове все переводить, где там какие строки… Не очень удобно, но это правда жизни, это удобство, то что мы можем себе позволить на языках, на высокоуровневых языках. Давайте посмотрим теперь в программном коде как же теперь у нас происходит работа с двухмерными массивами.

   1:  using System;
   2:   
   3:  // Массивы (двумерный массив).
   4:   
   5:  namespace Arrays
   6:  {
   7:      class Program
   8:      {
   9:          static void Main()
  10:          {
  11:              int[,] array = new int[3, 3];
  12:               
  13:              array[0, 0] = 1;
  14:              array[0, 1] = 2;
  15:              array[0, 2] = 3;
  16:   
  17:              array[1, 0] = 4;
  18:              array[1, 1] = 5;
  19:              array[1, 2] = 6;
  20:   
  21:              array[2, 0] = 7;
  22:              array[2, 1] = 8;
  23:              array[2, 2] = 9;
  24:               
  25:              Console.Write(array[0, 0]);
  26:              Console.Write(array[0, 1]);
  27:              Console.Write(array[0, 2]);
  28:              Console.Write("\n");
  29:              Console.Write(array[1, 0]);
  30:              Console.Write(array[1, 1]);
  31:              Console.Write(array[1, 2]);
  32:              Console.Write("\n");
  33:              Console.Write(array[2, 0]);
  34:              Console.Write(array[2, 1]);
  35:              Console.Write(array[2, 2]);
  36:                         
  37:              // Delay.
  38:              Console.ReadKey();
  39:          }
  40:      }
  41:  }

На 11 строке мы создаем двухмерный массив целочисленных элементов с именем array размерностью 3х3. Матрица третьего порядка. Смотрим, и заполняем этот массив значениями. Обращаясь по индексам. Давайте чуть-чуть пошагаем. Мы не будем долго это все прошагивать. Наведем сюда. Смотрите, как Visual Studio нам помогает красиво индексировать эти массивы. Но отображает она их как? Как она их отображает? Линейно, обратите внимание, линейно. Смотрите, считайте что нулевая строка, первая строка, вторя строка. Вот пошли столбцы. Второй индекс относится к столбцам. Давайте сейчас чуть-чуть прошагаем и заполним первую строку. Смотрим, что у нас здесь. Смотрите, заполнилось. Дальше. Вот это мы видим. Смотрите, видите? Мы заполнили массив. Вы сейчас меня спросите: «А можно ли двухмерные массивы заполнять в циклах? Или нам придется с ними работать так как вот здесь?» Давайте посмотрим, вы как думаете? Конечно же можно. Зачем бы мы тогда создавали эти массивы, если бы они не работали с циклами. Массив и цикл как брат и сестра, они должны работать вместе.

   1:  using System;
   2:   
   3:  // Массивы (двумерный массив).
   4:   
   5:  namespace Arrays
   6:  {
   7:      class Program
   8:      {
   9:          static void Main()
  10:          { 
  11:              int[,] array = new int[3, 3];
  12:               
  13:              // Заполнение массива
  14:              for (int i = 0; i < 3; i++)
  15:              {
  16:                  for (int j = 0; j < 3; j++)
  17:                  {
  18:                      array[i, j] = i*j+1;
  19:                  }
  20:              }
  21:   
  22:              for (int i = 0; i < 3; i++)
  23:              {
  24:                  for (int j = 0; j < 3; j++)
  25:                  {
  26:                      Console.Write("{0} ", array[i, j]);
  27:                  }
  28:                  Console.Write("\n");
  29:              }
  30:             
  31:              
  32:              // Delay.
  33:              Console.ReadKey();
  34:          }
  35:      }
  36:  }

Смотрим, на 11 строке… Я сейчас открою предыдущий пример, чтобы нам сравнить удобство использования массивов. Значит мы здесь создаем двухмерный массив целочисленных элементов размерностью 3х3, матрица третьего порядка. И начинаем заполнять массив элементами. Помните, мы выводили строку из звездочек? Не строку, а квадратик из звездочек. Помните? Цикл вложенный в цикл. Тоже самое. Мы начинам заполнять строку за строкой. И здесь бы хотелось пошагать. Здесь мы видим, что это некрасивый, неудобный, неправильный способ. Но зато он хорошо показывает обращение к массиву. Мы видим, что вот этот первый цикл for занимается чем? Заполнением массива элементами, а вот этот второй выводом значений каждого элемента массива на экран. Возможно вам покажется немного запутанной эта конструкция. Как же он работает. Но мы сейчас с вами пошагаем. Мы сейчас посмотрим. Давайте возьмем и просто пошагаем через F11. Мы просто создали пустой массив. Смотрите, все в нулях. Смотрите, массив три на три. I = 0, j = 0. Обратите внимание, 0,0. Значит i = 0, j = 0. И мы присваиваем смотрите что. Произведение индексов счетчиков i*j+1. Видите? Вот это умножить на это +1. 1? Да просто для оттенка. И значит ноль умножить на ноль - будет ноль, плюс 1 = 1. Смотрим, вот сюда мы что запишем? Что? 1. Давайте попробуем выполнить его. Выполнились, смотрим срочно бежим сюда. 1. Увеличили j, он стал равен 1. 1 меньше 3? Меньше. Идем сюда, смотрим 1*0 = 0. 0+1 = 1. Смотрим, 1. Еще раз, смотрим, 1. А почему 1? J уже равен 2, но так как счетчик верхнего цикла постоянно равен 0, он нам будет постоянно убивать все интересное вот здесь. Вот сейчас он станет равным единице. Сейчас мы готовы туда перейти. Сейчас мы выйдем с этого цикла. Увеличили его. I = 1. Входим во внутренний цикл. Идем вот сюда. J = 0, i = 1, 1*0 = 0, 0+1 =1. Снова же. Идем сюда. J = 1, i = 1, 1*1+1 = 2/ Видите да? Смотрите, как просто происходит заполнение цикла некоторыми значениями. Мы могли бы заполнить случайными значениями, или действительно вот допустим расчетными значениями, что мы рассчитали. Хорошо. Давайте здесь поставим break point. Мы понимаем, что здесь у нас массив заполняется. Нажимаем F5. Выполнились до 22 строки. Нажимаем, наводим на array. Вот такие значения у нас попали в наш трехмерный массив в матрицу третьего порядка 3х3. Теперь у нас остается что? Выводить это все на экран. Обратите внимание, индексы, то есть счетчики итераций циклов будут совпадать с чем? С индексами в массиве. И по ним мы будем возвращаться и каждый элемент поочередно выводить на экран. Просто? Просто. Смотрите, как интересно проходит работа с двухмерными массивами. Конечно скажу, что чаще используются одномерные массивы. Но и двухмерные достаточно часто используются. Заходим в следующий пример и смотрим что у нас происходит здесь.

   1:  using System;
   2:   
   3:  // Массивы (двумерный массив).
   4:   
   5:  namespace Arrays
   6:  {
   7:      class Program
   8:      {
   9:          static void Main()
  10:          {
  11:              // Компилятор определяет размер массива на основании выражения инициализации.
  12:              int[,] array = {
  13:                               { 1, 2, 3 },
  14:                               { 4, 5, 6 },
  15:                               { 7, 8, 9 }
  16:                             };
  17:   
  18:              Console.WriteLine(array);
  19:              
  20:   
  21:              for (int i = 0; i < 3; i++)
  22:              {
  23:                  for (int j = 0; j < 3; j++)
  24:                  {
  25:                      Console.Write("{0} ", array[i, j]);
  26:                  }
  27:                  Console.Write("\n");
  28:              }
  29:   
  30:   
  31:              // Delay.
  32:              Console.ReadKey();
  33:          }
  34:      }
  35:  }

Здесь мы тоже создаем двухмерный массив, но только с использованием чего? Как он называется? Блок инициализатора. И внутри этого блока инициализатора мы вкладываем еще три блока инициализатора. Смотрите, как бы три строки. Если бы мне нужно было бы работать с матрицей. То мне конечно иногда удобней представить ее вот так. Смотрите, я представил матрицу третьего порядка. И дальше снова мы видим знакомый алгоритм вывода элементов каждого массива на экран. Именно вот этот алгоритм мы и рассматривали в предыдущем примере, когда выводили на экран значение каждого элемента массива. Вам остается только взять пошагать и получить enjoy от изучения работы массивов. А мы с вами переходим дальше.

   1:  using System;
   2:   
   3:  // Массивы состоящие из одного элемента.
   4:   
   5:  namespace Arrays
   6:  {
   7:      class Program
   8:      {
   9:          static void Main()
  10:          {
  11:              int[] vector = new int[1];
  12:              vector[0] = 100;
  13:              Console.WriteLine(vector[0]);
  14:   
  15:   
  16:              int[,] matrix = new int[1, 1];
  17:              matrix[0, 0] = 200;
  18:              Console.WriteLine(matrix[0, 0]);
  19:   
  20:   
  21:              // Delay.
  22:              Console.ReadKey();
  23:          }
  24:      }
  25:  }

Обратите внимание, здесь идет вот такой частный случай. Массив может состоять также из одного элемента, как и в математике. Кто сказал, что матрица не может быть, не может состоять их одной строки и одного столбца. А так как массивы. Это единственный способ, чтобы нам представить математические матрицы, например, то соответственно такая возможность должна быть заложена, чтобы провести хоть какую-то проекцию на математику, на линейную алгебру. И смотрите, чтобы нам создать массив состоящий из одного элемента, мы создаем массив состоящий из целочисленных элементов vector размерностью 1 элемент. И вот по индексу 0 присваиваем значение 100. Ну это относится к одномерным массивам. Одномерные массивы иногда называют вектором. Что такое вектор в математике? Однонаправленный отрезок. А на 16 строке мы создаем двухмерный массив целочисленных элементов размерностью 1х1 с именем matrix. И для того чтобы нам заполнить этот единственный элемент нужно обратится по его индексу. Вот он лежит один несчастненький, одинокий с индексом 0,0. Просто? Просто. Ну это такое частные случаи. Я не думаю, что это вы часто будете использовать такие массивы. Конечно если вы не будете работать с какими-то математическими расчетами, например, с финансовыми расчетами или еще с какими-то, где используется линейная алгебра и используются массивы. Хорошо. А мы с вами подходим теперь к рассмотрению трехмерный массивов. И как всегда перейдем сначала к презентации. Давайте посмотрим на общее представление трехмерного массива. В голове его можно представить вот так. Как трехмерное пространство. Абсцисса, ордината, аппликата. Мы видим, что у нас имеются такие блоки. С чем мы можем их проассоциировать, например. Первое что приходит – это библиотека. Например, библиотека. Идет одна этажерка, за ней идет вторая этажерка, за ней третья с книгами. Обратите внимание, каждая этажерка состоит из трех полочек и трех секций. Видите да? И представьте, что вы библиотекарю говорите: «Дайте мне пожалуйста такую книгу.» Она отрывает свой каталог, находит индекс этой книги. Например, индекс этой книги – 2,1,2. Она идет ко второй этажерке. 2,1,2. Находит на ней первую полку. Она считает все с нуля. И находит на ней вторую ячейку. И вот здесь находится ваша книга по дифференциальном исчислению. Фихтенгольц допустим. А дайте мне еще Теорию вероятности Елены Вентцель. Она берет и смотрит, где же она находится? 1,0,1. Она подходит к первой этажерке, нулевая полка, первая ячейка. Вот здесь хранится книга Елены Вентцель «Теория Вероятности». Смотрите, как просто. Вот так же и мы представляем себе условно трехмерные массивы, как этажерки, которые условно идут друг за другом. Синтаксис создания этого массива. Вот он у нас наверху. Мы создаем трехмерный массив… Как это определить? А вот пустые места перед запятой, между запятыми и после запятой. Три пустых места. Потому что мы уже говорили, чтоб создать четырехмерный массив нужно еще одну запятую поставить. Значит мы создаем трехмерный массив элементов типа byte, или элементов типа book – книга. Значит мы создаем трехмерный массив элементов типа byte с именем array размерностью 3х3х3. Три этажерки, три полки на этажерке и три ячейки на каждой полке. Просто? Просто. Но если двухмерный в памяти понятно, ну хотя бы память все-таки линейная и одномерная. Покажите как они выглядят. Хорошо давайте посмотрим. Обратите внимание, как же выглядит трехмерный массив в памяти, в линейной памяти. ОЗУ – линейная. Просто последовательная цепочка адресов, табличек, которые прикручены к каждому байту. Значит смотрим, aaray у нас называется полностью вся наша библиотека, состоящая из этажерок. Значит смотрите, что мы здесь создаем. Мы создаем трехмерный массив элементов типа book – книга с именем array с размерностью 2 этажерки. На каждой этажерке – две полки. На каждой полке – две ячейки. Если здесь у нас было три этажерки по три полки и по три ячейки. То представьте, что мы создадим такие по две. Давайте выделим, и посмотрим как оно у нас будет 2х2х2. У нас будут вот эти и вот эти. Вот такое у нас будет. Да? Здесь мы можем провести вот так, чтобы вот такой маленький кубик нарисовать. Все остальное проигнорируем. Хорошо. Возвращаемся и смотрим, как же будет вот такая библиотека с двумя этажерками, на каждой по две полки, два столбца, выглядеть в одномерном преставлении. Смотрим, где наша этажерки? Помогите мне. Вот они. Первая этажерка и вторая этажерка. Ну мы здесь себе в голове дорисуем, что здесь у нас имеется еще два байтика, потому что в слайд не помещается. Получается, что на каждой этажерке у нас находится по две полки. Вот одна этажерка и другая этажерка. Давайте выделим полочки на каждой этажерке. Вот у нас идет одна полка, нулевая полка и вторая полка. Вот они две, видите? И соответственно на каждой полке у нас имеется что? По две ячейки в которых могут находится книги. Ну соответственно и здесь так же и здесь также. Теперь эту конструкцию можем спроецировать и на вторую этажерку. Хорошо. Думаю что здесь предельно понятно. А механизм? Пожалуйста, есть программисты, которые написали эту программу, которая и имитирует работу такой конструкции, как многомерный массив. Многомерного массива физически не существует. Это иллюзия. Есть специальная программа, которая имитирует его работу. Зачем? Чтобы высокоуровневому программисту позволить обращаться вот к такой сложной конструкции так, как будто бы у нас есть многомерные массивы. Но мы высокоуровневые программисты на С# даже этого не знаем и этого не надо знать. Это наверное я вам лишнюю информацию рассказал. Просто, чтобы вы знали. Это интересно. А может быть кто-то знает и ему действительно интересно. Так, а мы с вами теперь хотим перейти и посмотреть как же у нас в коде происходит работа с трехмерными массивами. Заходим снова же в Visual Studio и смотрим.

   1:  using System;
   2:   
   3:  // Массивы (трехмерный массив).
   4:   
   5:  namespace Arrays
   6:  {
   7:      class Program
   8:      {
   9:          static void Main()
  10:          {
  11:              int[, ,] array = new int[3, 3, 3];
  12:   
  13:              array[0, 0, 0] = 1;
  14:              array[0, 0, 1] = 2;
  15:              array[0, 0, 2] = 3;
  16:              array[0, 1, 0] = 4;
  17:              array[0, 1, 1] = 5;
  18:              array[0, 1, 2] = 6;
  19:              array[0, 2, 0] = 7;
  20:              array[0, 2, 1] = 8;
  21:              array[0, 2, 2] = 9;
  22:   
  23:              array[1, 0, 0] = 1;
  24:              array[1, 0, 1] = 2;
  25:              array[1, 0, 2] = 3;
  26:              array[1, 1, 0] = 4;
  27:              array[1, 1, 1] = 5;
  28:              array[1, 1, 2] = 6;
  29:              array[1, 2, 0] = 7;
  30:              array[1, 2, 1] = 8;
  31:              array[1, 2, 2] = 9;
  32:   
  33:              array[2, 0, 0] = 1;
  34:              array[2, 0, 1] = 2;
  35:              array[2, 0, 2] = 3;
  36:              array[2, 1, 0] = 4;
  37:              array[2, 1, 1] = 5;
  38:              array[2, 1, 2] = 6;
  39:              array[2, 2, 0] = 7;
  40:              array[2, 2, 1] = 8;
  41:              array[2, 2, 2] = 9;
  42:   
  43:   
  44:              for (int i = 0; i < 3; i++)
  45:              {
  46:                  for (int j = 0; j < 3; j++)
  47:                  {
  48:                      for (int k = 0; k < 3; k++)
  49:                      {
  50:                          Console.Write("{0} ", array[i, j, k]);
  51:                      }
  52:                      Console.Write("\n");
  53:                  }
  54:                  Console.Write("\n");
  55:              }
  56:   
  57:              // Delay.
  58:              Console.ReadKey();
  59:          }
  60:      }
  61:  }

На 11 строке мы создаем трехмерный массив целочисленных элементов. Значит каждый элемент будет из четырех байт. Толстые книги стоят. Еще раз мы создаем трехмерный массив целочисленных элементов с именем array размерности 3х3х3. Трехмерное пространство описывается ими. Абсцисса, ордината, аппликата. Значит три этажерки, на этажерке три полки, и каждая полка разделена еще на три секции. Представим, что у нас такая супер узкая библиотека. Теперь смотрим, смотрите как мы их заполняем. Помните? Когда мы брали книги с полки. Вот, обратите внимание, представьте себе такую библиотеку в трехмерном виде, проиндексируйте все ячейки и скажите библиотекарше, что вот сюда мы помещаем книгу №1, сюда книгу №5, ну и проассоциировали эти книги. Просто? Просто. Давайте теперь пошагаем, посмотрим как это выглядит. Нам важно посмотреть как вот здесь выглядит. Смотрите, тем не менее Microsoft предоставляет нам какое? Линейное представление трехмерного массива. Все равно линейное. Видите, с какими индексами? Видите, что этот 0 – этажерка нулевая, первая, вторая. Так, ну мы сейчас поколупаемся сейчас в нулевой этажерке. У нее идет самая верхняя полка. Дальше идет средняя полка и нижняя полка. Самая верхняя пока у нас имеет ячейки 0, под ней идет вот эта ячейка на первой полке, под ней идет вот эта ячейка. То есть идет некое образование столбца вот из вот этих третьих индексов. Теперь мы берем с вами заполняем ее. Смотрите, мы заполнили первую этажерку книгами, все остальные пока пустые. Пошли на обед, студенты пошли на обед. Хорошо. Заполняем следующую. Смотрим, заполнили вторую этажерку, пошли домой, пришли утром и заполнили последнюю этажерку. Расставили книги, протерли пыль. Давайте посмотрим, как у нас заполнено здесь все. Видите? Все у нас здесь заполнено. Все полочки у нас заполнены. Теперь нас интересует автоматический перебор всех элементов трехмерного массива. Нам нужно автоматически пробежать и вывести на экран и продиктовать все имена книг. Для этого нам нужен цикл, который вложен в цикл, который вложен еще раз в цикл. Хорошо. Мы понимаем, что вот этот самый внутренний цикл должен выводить что? Строки. Вот этот выводит ячейки в строке, формирует строку. Вот этот позволяет переводить каретку. Он заставляет библиотекаршу сверху вниз нагибаться и смотреть на книги на нижних полках. А вот этот что делает? Он заставляет от этажерки к этажерке переходить библиотекарше. Вы видите? Давайте хотя бы несколько итераций пройдем. Там смотрим. Мы сейчас стоим у нулевой этажерки. Сейчас мы смотрим на верхнюю полку и начинаем работать с ячейкам. Смотрим, что у нас здесь происходит? Где наш array? Вот мы к ней обращаемся и что мы видим на экране? Мы выели вот 1. Заметили? Хорошо. Дальше смотрим. В следующей ячейке самой первой полки, самой первой этажерки, и последняя ячейка самой верхней полки первой этажерки. Куда переходим? Начинаем нагибаться ниже. Вот мы сейчас смотрим на среднюю полку. Дальше что мы делаем? Нагибаемся сильно и смотрим что там в самом низу возле пола. Так посмотрели. Смотрите, мы полностью исследовали первую этажерку. Что мы делаем дальше? Переходим к следующей этажерке. Поднимаемся, встаем, обходим наш шкафчик и идем к следующей. Смотрите, как просто. Вот так у нас просто идет работа с трехмерными массивами. По частоте использования чаще всего в программировании используются одномерные массивы. Двухмерные используются тоже часто, но только лишь для тех, кто работает чаще всего с матрицами с линейной алгеброй и вот с такими табличными представлениями. Трехмерные массивы. Они используются гораздо реже, потому что здесь конечно же нужны какие-то трехмерные представления, которые просто так не выдумаешь на ровном месте. Правда это не идет какой-то совсем тривиальный пример. Так а мы переходим дальше.

   1:  using System;
   2:   
   3:  // Массивы (трехмерный массив).
   4:   
   5:  namespace Arrays
   6:  {
   7:      class Program
   8:      {
   9:          static void Main()
  10:          {
  11:              int[, ,] array = 
  12:              { 
  13:                 { { 1, 2, 3 }, { 4, 5, 6 }, {7, 8, 9} }, 
  14:                 { { 1, 2, 3 }, { 4, 5, 6 }, {7, 8, 9} }, 
  15:                 { { 1, 2, 3 }, { 4, 5, 6 }, {7, 8, 9} }                                  
  16:              };
  17:   
  18:             
  19:              for (int i = 0; i < 3; i++)
  20:              {
  21:                  for (int j = 0; j < 3; j++)
  22:                  {
  23:                      for (int k = 0; k < 3; k++)
  24:                      {
  25:                          Console.Write("{0} ", array[i, j, k]);
  26:                      }
  27:                      Console.Write("\n");
  28:                  }
  29:                  Console.Write("\n");
  30:              }
  31:   
  32:              // Delay.
  33:              Console.ReadKey();
  34:          }
  35:      }
  36:  }

Вот пожалуйста. Здесь мы уже используем блок инициализатора. Второй способ создания трехмерного массива. Это у нас что такое? Это библиотека. Это этажерки. Это полки. А вот это идут столбцы. Еще раз. Вот она наша этажерка. Это одно из измерений, второе и вот третье измерение. И знакомый наш цикл, который вложенный в цикл, который вложенный в цикл. Зачем? Для того чтобы мы могли подойти по одному из измерений. То есть подходить к этажеркам. Извините меня за такие сравнения, но я думаю, что многим будет понятно. Не хотелось бы совсем на математический лад перекладывать, потому что возможно, большинство случаев, большинство слушателей могут воспринять вот в такой простой игровой манере. Вот видите, мы подходим к этажеркам, начинаем проходить по полкам, а это у нас ячейки на отдельные полки. Те звездочки, которые мы рисовали, когда выводили квадратик. Хорошо. Конечно вас интересовали и большие измерения чем, например, трехмерные измерения. Четырехмерные измерения. Вот скажите, а как выглядят четырехмерные измерения? Очень просто. Абсцисса, ордината, аппликата, еще одна координатная ось, например время. Когда мы смотрим как у нас со временем движется тело. Вот, допустим, четырехмерная система координат. Часто конечно не используется четырехмерная система, но бывает используется, например, в какой-нибудь аналитике, многомерной аналитике. Возможно вы слышали такое понятие как OLAP кубы. Ну в общем имеется даже в бизнесе многомерная аналитика, где нам нужно проследить взаимосвязи различных параметров. Мы не будем об этом много говорить, кому интересно, у многомерных аналитиках можно узнать, почитать. Хорошо. Для того, чтобы нам создать четырехмерный массив нам нужно поставить три запятых. Смотрите, первое измерение, второе, третье, четвертое. То есть измерения считаются условно этими пробелами. Далее мы создаем 2х2х2х2.

   1:  using System;
   2:   
   3:  // Массивы (четырехмерный массив).
   4:   
   5:  namespace Arrays
   6:  {
   7:      class Program
   8:      {
   9:          static void Main()
  10:          {
  11:              int[, , ,] array = new int[2, 2, 2, 2];
  12:   
  13:              array[0, 0, 0, 0] = 0x0;
  14:              array[0, 0, 0, 1] = 0x1;
  15:              array[0, 0, 1, 0] = 0x2;
  16:              array[0, 0, 1, 1] = 0x3;
  17:   
  18:              array[0, 1, 0, 0] = 0x4;
  19:              array[0, 1, 0, 1] = 0x5;
  20:              array[0, 1, 1, 0] = 0x6;
  21:              array[0, 1, 1, 1] = 0x7;
  22:   
  23:              array[1, 0, 0, 0] = 0x8;
  24:              array[1, 0, 0, 1] = 0x9;
  25:              array[1, 0, 1, 0] = 0xA;
  26:              array[1, 0, 1, 1] = 0xB;
  27:   
  28:              array[1, 1, 0, 0] = 0xC;
  29:              array[1, 1, 0, 1] = 0xD;
  30:              array[1, 1, 1, 0] = 0xE;
  31:              array[1, 1, 1, 1] = 0xF;
  32:   
  33:   
  34:              for (int i = 0; i < 2; i++)
  35:              {
  36:                  for (int j = 0; j < 2; j++)
  37:                  {
  38:                      for (int k = 0; k < 2; k++)
  39:                      {
  40:                          for (int l = 0; l < 2; l++)
  41:                          {
  42:                              Console.Write("{0:X} ", array[i, j, k, l]);
  43:                          }
  44:                          Console.Write("\n");
  45:                      }
  46:                      Console.Write("\n");
  47:                  }
  48:                  Console.Write("\n");
  49:              }
  50:   
  51:              // Delay.
  52:              Console.ReadKey();
  53:          }
  54:      }
  55:  }

На библиотеке можно представить? Представьте себе такую ситуацию, что у нас имеется четырехмерная библиотека и все эти этажерки движутся во времени. Библиотекарша будущего она не собирается ходить между этажерками. Расставьте мне пожалуйста этажерки, чтобы они крутились по кругу вокруг меня с определенной скоростью. Она сидит и вы к ней подходите и говорите: «Дайте мне пожалуйста книжечку Мат статистика Гмурмана» Она говорит: «Подождите 3 секунды» Через три секунды подойдет ваша полка и я с нее выдерну книжку. Представляете себе ситуацию? Это условный и смешной такой пример, где можно было бы с библиотекой придумать четырехмерное пространство. Замечательно. Обратите внимание, также указываем все измерения и мы понимаем что и четырехмерные массивы представлены тоже одномерно в ОЗУ. И соответственно, для того чтобы нам перебрать это массив нам нужен четвертый цикл. Смотрите, Это идут сами ячейки в полке, это идет полка, это идет этажерка, а вот это некая плоскость, некий механизм, который вращает вереницу этажерок вокруг библиотекарши в библиотеке. И ей нужно что? Просто подождать определенное время, пока нужная полка не подойдет к ней. Хороший пример четвертого измерения – это есть художественный фильм «Гиперкуб». Их три серии, первая какая-то очень мрачная, он вообще такой мрачный, но там суть такая, что был куб состоящий из секций. Эти секции двигались, и для того чтобы пленникам выбраться с этого куба, и нужно было рассчитать номера комнат, и когда они подойдут к специальному выходу, там надо было выскочить. Вот они там обыгрывали вот это четырехмерное пространство. Ну с нашей волшебной библиотекой тоже самое могло быть. Хорошо, а мы переходим к следующему примеру и посмотрим, возможно ли с помощью блока инициализатора представить нам четырехмерный массив. Нет проблем. Можно. Обратите внимание, и что же здесь.

   
   1:  using System;
   2:   
   3:  // Массивы (четырехмерный массив).
   4:   
   5:  namespace Arrays
   6:  {
   7:      class Program
   8:      {
   9:          static void Main()
  10:          {
  11:              int[, , ,] array = 
  12:              {
  13:                {
  14:                  { { 0x0, 0x1 }, {0x2, 0x3 } },
  15:                  { { 0x4, 0x5 }, {0x6, 0x7 } }
  16:                },
  17:                {
  18:                  { { 0x8, 0x9 }, {0xA, 0xB } },
  19:                  { { 0xC, 0xD }, {0xE, 0xF } }
  20:                }
  21:              };
  22:   
  23:   
  24:              for (int i = 0; i < 2; i++)
  25:              {
  26:                  for (int j = 0; j < 2; j++)
  27:                  {
  28:                      for (int k = 0; k < 2; k++)
  29:                      {
  30:                          for (int l = 0; l < 2; l++)
  31:                          {
  32:                              Console.Write("{0:X} ", array[i, j, k, l]);
  33:                          }
  34:                          Console.Write("\n");
  35:                      }
  36:                      Console.Write("\n");
  37:                  }
  38:                  Console.Write("\n");
  39:              }
  40:   
  41:              // Delay.
  42:              Console.ReadKey();
  43:          }
  44:      }
  45:  }

Вот эта наша волшебная библиотека, это два измерения времени. Представьте, что у нас условно дискретно две полки разбиваются на две части по времени, и библиотекарша ждет, пока подставится полка. Здесь у нас, это что такое? Этажерки, которые двигаются вокруг библиотекарши, а вот это полочки на этажерке. А вот это что у нас? Ячейки. Просто? Просто. Хорошо. И мы переходим с вами к еще одной интересной разновидности массивов – это зубчатые массивы. Это Jagged Arrays как их называют. А почему эти массивы называют зубчатыми? Их нужно просто увидеть на презентации как они выглядят. Давайте мы сейчас перейдем на презентацию. Он нам уже встречался здесь. Видите, как он выглядит внешне. Такой неоднородный. Да? Кажется как будто зубчики какой-то шестеренки торчат. Но не смотря на его абстрактное представление именно вот такое, зубчиками выглядит, но тем не менее, но это уже последнее изложение про массивы. Тем не менее он тоже линейный. Ладно, показываю как он линейный. Смотрим, обратите внимание, наш зубчатый массив. Смотрите, по сути, давайте посмотрим на его создание. Для того, чтобы нам создать такой зубчатый массив нам нужно указать вот такую пару пустых открывающихся и закрывающихся квадратных скобок. Указать тип элемента такого массива. Здесь как бы, смотрите. Как бы говорится, смотрите, У нас создается одномерный массив из одномерных массивов разной длины. С именем Array. Смотрите, мы говорим, что у нас будет создано три вот таких подмассива в этом массиве. Что это значит? Давайте повыделяем, посмотрим. Вот смотрите, идет весь наш массив. Что в нем есть? Вот у нас идет нулевой индекс, первый индекс, второй индекс. Смотрим, вот у нас идет один, второй и третий. Видите, у нас здесь имеется три отдельных подмассива. Смотрим, так как мы создали три массива, мы создали массив в котором три подмассива вложенных, и каждый из этих массивов разной длины. Обратите внимание, в массиве array вложен один массив на 2 элемента, представьте, что это просто такая полка, на 2 элемента, второй на 4 элемента, а этот самый нижний на 3 элемента. И если это представить такой полочкой, то вот мы понимаем какая хитрая конструкция которая состоит вот из вот таких ячеек. То есть еще раз смотрим. Зубчатый массив называется зубчатым потому что он внешне напоминает зубчики шестеренки, это раз. Потом, зубчатый массив – это массив, который состоит из массивов разной длины. И мы видим, что массив array, смотрите, видите что мы нулевому элементу присваиваем? Новый полноценный массив байтовых элементов размерностью в два элемента. По первому индексу еще один массив лежит. То есть это массив, состоящий из массивов. Обратите внимание, только вот этот первый индекс указывает количество подмассивов в большом массиве. Как же здесь представляется? Да, это специальная программа, написана программистами, которые и контролируют работу вот таких конструкций. Конечно же это все искусственные конструкции. Это все просто удобство для представления вот таких сущностей, которые представляют собой массив из массивов разной длины. Сложно ли с ним работать? Нет не сложно. Как мы их создаем мы уже видим. Сейчас мы перейдем к программному коду. По сути все массивы достаточно простые сущности. Могут возникать какие-то сложности с запоминанием синтаксиса, но я думаю что раз другой вы попробуете их создать, сделаете рекомендованные задания практические, которые идут в методических пособия к каждому уроку, и я думаю, что ваш мозг это быстро запомнит. Тем более вы видите насколько это интересно. Смотрим.

   1:  using System;
   2:   
   3:  // Зубчатые массивы (Jagged Array).
   4:   
   5:  namespace Arrays
   6:  {
   7:      class Program
   8:      {
   9:          static void Main()
  10:          {
  11:   
  12:              int[][] jagged = new int[3][];
  13:   
  14:              jagged[0] = new int[] { 1, 2 };
  15:              jagged[1] = new int[] { 1, 2, 3, 4, 5 };
  16:              jagged[2] = new int[] { 1, 2, 3 };
  17:   
  18:   
  19:              // Во внешнем цикле выполняется проход по всем вложенным массивам.
  20:              for (int i = 0; i < jagged.Length; ++i)
  21:              {
  22:                  // Во внутреннем цикле выполняется обращение к каждому элементу вложенного массива.
  23:                  for (int j = 0; j < jagged[i].Length; ++j)
  24:                  {
  25:                      Console.Write("{0} ", jagged[i][j]);
  26:                  }
  27:                  Console.Write("\n");
  28:              }
  29:              
  30:   
  31:              // Delay.
  32:              Console.ReadKey();
  33:          }
  34:      }
  35:  }

На 12 строке мы создаем зубчатый массив. Когда я вижу эту пару я сразу говорю, что это зубчатый массив или его еще называют Jagged Array. Мы создаем зубчатый массив из трех подмассивов. Смотрите, нулевому элементу мы присваиваем массив из двух элементов, первому – массив из пяти элементов, и второму – массив из трех элементов. Я уже слышу, что вы говорите шагать. Все уже шагаю. Так создали, еще ничем не заполнили. Ага, пока у нас имеется массив из трех эллементов, но пока они null – пустые. Посоздавали их. Давайте сейчас посмотрим. Смотрите, ага, они уже созданы. Смотрите, вы видите? Два элемента, пять элементов, три элемента. Вы видите? Массив Jagged состоит из трех подмассивов. И теперь у вложенных массивов нет имен. А как они, как они индексирутся. Вы видите? Нулевой подмассив, первый подмассив. Здесь заметьте, даже говорится сколько элементов и какой тип этого подмассива. Хорошо, а как нам теперь с ними правильно работать. Давайте смотрим. Сам Jagged у него имеется свойство length, чем у оно равно? 3. В нем лежит три подмассива. Чему равен length. Вот сразу показываю чему равен length = 3. Замечательно! Значит, 0<3? Меньше. Мы сейчас будем обходить по очереди все вот эти массивы. Просто такая техника обхода. Так. Заходим во внутренний цикл. И внутренний цикл бежит почему? Вот по этим уже внутренним массивам. Значит, мы сейчас решили взять какой массив? Вот этот – нулевой, то есть нулевой подмассив, да? И теперь, обратите внимание, мы здесь берем индекс j. Смотрим. Ага. Jagged чему равно? Смотрите. Jagged. Сам jagged у нас равен 3. Видите? 3-м. Но jagged по индексу 0 – это что у нас такое? Это вот этот подмассив, видите? Мы сейчас стоим на нем. Jagged по нулевому индексу. Видите? Вот по нулевому индексу. Это подмассив, у которого имеется, смотрите, по сути, свое свойство length. Вот видите? У него есть свой length. Ну, так делать нельзя! Это я вам так просто показал, да? У него есть свое свойство length. Ага. И чему это свойство length равно? Раз, два. Смотрим. Два. Чудесно! Мы теперь идем дальше. И смотрим теперь. Обращаемся jagged к нулевому подмассиву и к нулевому элементу в этом подмассиве. Вот к единичке. Следующая итерация. К чему мы обращаемся? Все-таки еще нулевой подмассив – мы еще не выходили сюда. И здесь первый элемент, видите? Выводим его на экран. Смотрите мы прошлись… Смотрите, что мы видим: 1, 2. Мы вывели вот этот подмассив. Хорошо. Смотрим дальше. Так. Выводим. /n – это перевод курсора на новую строку. Смотрите. Видите, где сейчас курсор? Только мы сейчас выполним /n – это специальная esc-последовательность. Они так и называются esc-последовательностью. Почитайте о них тоже на ресурсе MSDN. Смотрите, видите? Только мы выполнили /n – курсор перешел на новую строку. Просто? Просто. Так. Значит, мы только что вывели вот этот массив. Идем увеличиваем индекс. Так. Увеличили. Length – 3, i – 1. Вот. Мы сейчас пойдем по вот этому массиву. Смотрите. Выводим 1. Смотрите, 1 вывели. Выводим вот эту 2-ку. Вывели. Выводим – 3. Выводим – 4. Выводим – 5. Вывели 5. Смотрите. Вы видите? 5 вывелось. Смотрите, разной длины массивы. Замечательно! Так. Переводим строку, переводим курсор на новую строку. Видите вот где мы стоим? Видите? Так. Видите, у нас, как в фокусах все. Так. Замечательно! И что мы сейчас делаем? Переходим ко второму индексу: i равен 2 – ко второму подмассиву. Выводим что? 1, 2… Что? 3-ку. Смотрим. Вывели 3-ку, видите? Сейчас курсор переведем тоже, на всякий случай. Пам! Перевели курсор. Смотрите, курсор на новой строке. Смотрите, как просто работать с jagged arrays, с jagged массивами. Просто? Просто. Снова же, в каких-то случаях нам понадобится структурировать определенную информацию именно вот в такой форме. Скажите, а зачем? Ну, а может быть у вас имеется вот разное количество каких-то характеристик, и представьте, что вот здесь у вас будит их, допустим, 100000, да? К примеру, здесь их будет 2000, а здесь будет только 2. Смотрите, какая экономия памяти, а так бы вам здесь пришлось бы везде делать по 100 тысяч нулей, а мы с вами помним, что если мы создаем пустой массив, там все равно ОЗУ занимается, правда? Все равно ОЗУ выделяются байтики и заполняются нулями. Зачем? Чтобы в нашей программе висели пустые нули, которые никогда не будут использоваться. Мы и так вот это бедное ОЗУ бережем, стараемся его докупить больше, чтоб у нас его было, чтоб машина работала быстрее, правда? Поэтому первое, что на лицо экономия памяти, согласны? Это уже первое. Мы сейчас не говорим о каких-то аналитических тонкостях использования. Смотрим следующее.

   1:  using System;
   2:   
   3:  // Зубчатые массивы (Jagged Array).
   4:   
   5:  namespace Arrays
   6:  {
   7:      class Program
   8:      {
   9:          static void Main()
  10:          {
  11:   
  12:              int[][] jagged = new[]
  13:              {
  14:                 new int[] { 1, 2 },
  15:                 new int[] { 1, 2, 3, 4, 5 },
  16:                 new int[] { 1, 2, 3 }
  17:              };
  18:   
  19:              // Во внешнем цикле выполняется проход по всем вложенным массивам.
  20:              for (int i = 0; i < jagged.Length; ++i)
  21:              {
  22:                  // Во внутреннем цикле выполняется обращение к каждому элементу вложенного массива.
  23:                  for (int j = 0; j < jagged[i].Length; ++j)
  24:                  {
  25:                      Console.Write("{0} ", jagged[i][j]);
  26:                  }
  27:                  Console.Write("\n");
  28:              }
  29:   
  30:   
  31:              // Delay.
  32:              Console.ReadKey();
  33:          }
  34:      }
  35:  }

А что мы здесь видим? Мы здесь видим, что тоже самое мы можем сделать, то есть мы можем создать jagged array – зубчатый массив через использование блока инициализатора – мужской род. Инициализатора. Смотрите, видите? И мы просто в него вкладываем три нужных полноценных массива jagged array – зубчатый массив, массив массивов. Эти циклы мы только, что шагали. Вы помните, да? Если вам интересно вы можете пошагать его самостоятельно еще. Это тот же самый пример просто в другом представлении создания зубчатого массива через использование блока… Как? Инициализатора. Замечательно! А мы с вами переходим дальше. Обратите внимание! Мы уже подходим к концу. Мы подходим уже к концу. И вот этот пример. Он нам просто показывает то, что мы можем массивы передавать в качестве аргументов методов.

   1:  using System;
   2:   
   3:  namespace Arrays
   4:  {
   5:      class Program
   6:      {
   7:          static int[] ModifyArray(int[] array, int modifier)
   8:          {
   9:              for (int i = 0; i < array.Length; i++)
  10:              {
  11:                  array[i] = array[i] * modifier;
  12:              }
  13:   
  14:              return array;
  15:          }
  16:   
  17:          static void Main()
  18:          {
  19:   
  20:              int[] myArray = { 1, 2, 3, 4, 5 };
  21:   
  22:              myArray = ModifyArray(myArray, 5);
  23:   
  24:             
  25:              for (int i = 0; i < myArray.Length; i++)
  26:              {
  27:                  Console.Write("{0},",myArray[i]);
  28:              }
  29:   
  30:             
  31:              Console.ReadKey();
  32:          }
  33:      }
  34:  }

Обратите внимание! Вот мы создаем массив и передаем его в качестве аргумента метода, а уже в методе находится некий механизм обработки этого массива. Видите, как удобно? То есть правило следующее: мы можем массивы создавать и передавать в качестве аргументов методов. Видите, да? Создали массив, имеется метод. Мы можем массив передать внутрь другого метода. Запомните это. Такие вопросы тоже начинающие тоже, бывает, задают нашим тренерам. И теперь переходим, посмотрим еще одну интересную особенность: ключевое слово – params.

   1:  using System;
   2:   
   3:  // Ключевое слово params, позволяет определить параметр метода, принимающий переменное количество аргументов.
   4:   
   5:  namespace Arrays
   6:  {
   7:      class Program
   8:      {
   9:          static void ShowArray(params int[] array)
  10:          {
  11:              for (int i = 0; i < array.Length; i++)
  12:              {
  13:                  Console.Write("{0} ", array[i]);
  14:              }
  15:          }
  16:          
  17:          static void Main()
  18:          {
  19:              ShowArray(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
  20:   
  21:              // Delay.
  22:              Console.ReadKey();
  23:          }
  24:      }
  25:  }

Ну, мы знаем, что мы массивы можем передавать в качестве аргументов методов, да? То есть получается в нас, в данном случае, на 9-ой строке мы создаем метод с именем ShowArray. Видите, да? С одним аргументом, какого типа? Типа массива элементов целочисленного типа. Вы видите? Имя параметра, имя аргумента – array и ключевое слово – params. Что позволяет делать ключевое слово «params»? Обратите внимание! При вызове этого метода мы передаем сюда не массив, а что мы передаем? Вы скажите: мы сюда передаем какое-то переменное количество аргументов, да? Тем более целых. Заметьте, да? Мы сюда передаем не массив, а переменное количество аргументов. В итоге, что происходит? Странным образом, среда, она берет и формирует вот из этих аргументов настоящий массив и передает его вот сюда. Скажете: странно. Да, как? Давайте выполнимся. Смотрите. Вот они все вывелись. Смотрите, мы сюда передали просто десять непосредственных значений. Они взяли упаковались в массив. Видите, да? Но слово «упаковались»… Нельзя так говорить. Они преобразовались в массив. Видите? И вот этот внутренний механизм метода, видите? ShowArray сработал с ним, как с чем? С полноценным массивом. Вы видите? Вот. Как с массивом, то есть получается, что вот они попали вот сюда. Видите? Все вот эти параметры. Они превратились в массив. Если не совсем понятно – давайте откроем программу, которая называется .NET REFLECTOR и посмотрим. Если мы возьмем и дисассемблируем нашу программу, наш exe файл, как мы это уже когда-то делали, да? И посмотрим во что же превратилась наша программа, да? Смотрите, вот идет наш массив. Вот смотрите, видите? Видите, что мы видим? Наш метод Main, видите? Вот метод Main. Метод вызывается ShowArray. Видите, да? Вот мы можем в него зайти. Видите? Вот он – наш метод ShowArray. Видите? Вот он. Он случаен. Скажите: один в один. Хорошо. Так делаем Expand Methods и смотрите вот они наши значения: 1, 2, 3, 4, 5, 6, 7, 8, 9. Видите? Вот они. И в методе Main, обратите внимание, произошло создание массива элементов. Вы видите какое странное имя? Такое имя дал компилятор. Это не мы. Это вот здесь создалось вот такое странное имя. Видите, да? Вот такое странное имя создалось. Далее, указалась размерность массива. Видите? Он посчитал, сколько здесь элементов. Видите? Давайте мы вот сейчас это сделаем. Видите? Вот. Он посчитал, сколько вот здесь элементов: раз, два, три, четыре, пять, шесть , семь, восемь, девять, десять. Поставил его сюда. Потом каждый элементик… Смотрите, что он сделал. Нулевой элемент, то есть там первый элемент поместил сюда, второй – сюда. Сейчас, секундочку. Я сейчас перезапущусь. Выполнюсь. Так, F5. Возвращаемся. И здесь… Так. Потому что это может быть открылся не тот пример, наверное, да? Давайте мы тогда сделаем по-хитрому, по-другому. Возьмем сразу же Program. Так. Еще раз. Params. Open Folder in File Explorer. Открыли его, да? Заходим в папку bin. Debug. Вот этот Arrays20.exe. Так, заходим теперь снова же в REFLECTOR. Возьмем отсюда его удалим. Удалим, потому что, возможно, что-то я не то подготовил. Берем его, перетягиваем вот сюда. Пам! Вот он у нас получился. Эту папочку можно… Ну, сейчас мы ее закроем. Открываем. Вот он наш Program, класс Program. И мы видим, что в нем вот здесь происходит. Так! Ну, так как мы присваивали от нуля, смотрите, видите? Здесь уже что-то нам не то показывает сам REFLECTOR. Скорее всего, это ошибка уже… Потому что все-таки это сторонняя программа и она нам показывает, что здесь у нас имеется только девять элементов, хотя у нас, на самом деле, имеется десять. Видите? Несмотря на то, что мы… Ну, немножко, но некорректно, с ошибкой здесь нам отобразило. Ну, ничего страшного. Я вам уже говорил, что REFLECTOR – это специальная программа, которая позволяет взять готовый исполняемый файл, открыть его и прочитать чужие коды. Ну, насколько это хорошо, это вопрос спорный, но, тем не менее, Microsoft тоже может похвастаться, что у него открытые коды. Пожалуйста. А уже то, что кто там в заимствует какие-то идеи, в заимствует какие-то алгоритмы – это уже другая моральная составляющая или моральная, или криминальная – это уже разбираемся не мы, правда? Главное, чтобы мы целиком не брали за основу чужих программ, правда? Ну, а если мы там немножко почитаем, поучимся на каких-то программах – я думаю, что ничего страшного в этом нет, да? Тем более, все компании, практически, пишут одно и тоже, все делают одинаковые CRM c разными цветами. Так, практически… Ну, конкурируют там в мелочах. Хорошо. Ну, еще два слова о REFLECTOR. Обратите внимание: здесь можно выбрать язык отображения, можно посмотреть нашу программу, которую мы писали на C#, на Visual Basic, можно посмотреть ее на языке ManagedC++. Managed – это управляемый язык. Вот он здесь не показывается. Не поддержали разработчики. Язык MSIL – это как раз и есть вот этот промежуточный язык ассемблера для виртуальной машины. CLR – это Common Language Runtime. Это некая виртуальная машина, возможно вы знаете, в кибернетике и, вообще, в информатике это разновидность интерпретаторов компилирующего типа. Это не просто интерпретатор, это интерпретатор компилирующего типа. Вот здесь как раз имеются мнемоники, которые заменяют собой именно байт-код, который поступает на вход этой виртуальной машины. Но об этом мы говорим на отдельных курсах, на отдельных семинарах, разбираем вот этот язык. Просто знайте, что вот есть вот такие возможности у нас в этой программе REFLECTOR. Эта программа платная, есть другая программа еще, которую я вам могу посоветовать для изучения кодов программ. Это Dot Pic. Поэтому Dot Pic дисассемблер. Можете попробовать с ним. Ну, хотя и в REFLECTOR есть там trial период, который вот вы можете использовать бесплатно, для ознакомления. Хорошо. А мы возвращаемся к нашему примеру. Ключевое слово «params» позволяем, что сделать? Переменное число аргументов преобразовать во что? В целый массив. Вот как мы здесь видим произошло у нас. Только вот я не могу понять почему оно здесь… Вот проигнорировался нулевой элемент. Ну, я думаю, что это уже какой-то мелкий bug, недочет вот этой программы. Хорошо. И давайте мы смотрим еще правила по Params. Заходим в следующий пример – тоже описывает params, то есть Params.

   1:  using System;
   2:   
   3:  // Параметр с ключевым словом params, должен быть только один и стоять последним в списке параметров метода.
   4:   
   5:  namespace Arrays
   6:  {
   7:      class Program
   8:      {
   9:          static void ShowArray(string name, params int[] array)
  10:          {
  11:              Console.Write(name);
  12:   
  13:              for (int i = 0; i < array.Length; i++)
  14:              {
  15:                  Console.Write("{0} ", array[i]);
  16:              }
  17:          }
  18:   
  19:          static void Main()
  20:          {
  21:              ShowArray("Numbers: ", 0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
  22:   
  23:              // Delay.
  24:              Console.ReadKey();
  25:          }
  26:      }
  27:  }

Переменные – количество аргументов, которые преобразуются в массив. Давайте посмотрим. Здесь мы создаем метод ShowArray. Первый аргумент его строковой, второй аргумент – это массив помеченный params, потому что, если мы уберем ключевое слово params, обратите внимание, то нам вот так не позволено будет сделать, видите? Говорит: ну, все я теперь не понимаю, Александр, что ты хочешь преобразовать это в массив. Бери и делай полноценный массив, да? А если мы вернем ключевое слово params, то вот произойдет вот такая ситуация, что за нас среда разработки. Она возьмет сделает вот такую штуку: берет это вырезает, создает массив, вставляет, подставляет сюда имя массива. Вы это только что видели в программе REFLECTOR. Этот пример показывает еще одно правило, что если вы используете ключевое слово params, то оно может быть использовано только один раз в списке аргументов, потому что, если вы передаете несколько массивов, да? То вы можете использовать только один раз ключевое слово params и массив с этим ключевым словом должен идти самым последним в списке аргументов, потому что, если мы попытаемся поменять местами – это уже будет ошибка. Нам правила языка не позволят такого сделать. Хорошо. Вот такие интересные особенности мы еще с вами разобрали. И так как мы подошли с вами к концу урока сегодняшнего… Мы сегодня разбирали массивы, работу с массивами, их создание. Давайте мы повторим все, что мы сегодня с вами разбирали по презентации. Значит, мы с вами сегодня рассмотрели одномерные массивы, двухмерные массивы, трехмерные массивы, четырехмерные массивы. Пяти- рассматривали? Нет, не рассматривали. И рассмотрели зубчатые массивы. Значит мы поняли, что массив – это некая область памяти, которая специальным образом разделяется на элементы, это именованная область памяти, у нее есть имя, а у каждого элемента, который входит в эту область памяти есть индекс и к этой области памяти можем обращаться только по индексу. Массивы у нас бывают одномерные. Вот, пожалуйста, мы смотрели вот эти слайды. Здесь у нас синтаксис создания этого массива, одномерного массива. Вот мы рассмотрели способы создания одномерных массивов – достаточно просто. Далее, мы перешли уже к многомерным массивам, потому что зубчатые массивы, как мы понимаем, это разновидность многомерных массивов. Видите, вот три этажа там с разными торчащими полками, как в каком-нибудь юмористическом фильме, где умеют плохо обращаться, да? Там с инструментами. Далее, мы рассмотрели двумерные массивы полноценные, рассмотрели, как эти двухмерные массивы в действительности представляются в памяти. Далее, мы рассмотрели трехмерные массивы. Помните наши полки, наши этажерки в библиотеке и полки, и вот ячейки в них? Далее, мы рассмотрели, как же трехмерный массив представляется в памяти физически. Ну, вот да вот он представляется линейно. И мы рассмотрели с вами зубчатые массивы, также мы затронули много других интересных моментов. Там, четырехмерные массивы, работу ключевого слова params и многое другое. Хорошо. На этом мы заканчиваем наш урок по работе с массивами. Спасибо за внимание! До новых встреч!

Студенты также смотрят
C# 8.0 Стартовый
ПОДРОБНЕЕ
C# базовый (ООП)
ПОДРОБНЕЕ
C# Базовый (ООП) 2021
ПОДРОБНЕЕ
C# Углубленный
ПОДРОБНЕЕ
C# Универсальные шаблоны
ПОДРОБНЕЕ
Что нового в C# 6.0-7.0
ПОДРОБНЕЕ
C# 5.0 для профессионалов
ПОДРОБНЕЕ

Покупай подпискус доступом ко всем курсам и сервисам

Библиотека современных IT знаний в удобном формате

Выбирай свой вариант подписки в зависимости от задач, стоящих перед тобой. Но если нужно пройти полное обучение с нуля до уровня специалиста, то лучше выбирать Базовый или Премиум. А для того чтобы изучить 2-3 новые технологии, или повторить знания, готовясь к собеседованию, подойдет Пакет Стартовый.

Стартовый
  • Все видеокурсы на 3 месяца
  • Тестирование по 10 курсам
  • Проверка 5 домашних заданий
  • Консультация с тренером 30 мин
59.99 $
Оформить подписку
Базовый
  • Все видеокурсы на 6 месяцев
  • Тестирование по 16 курсам
  • Проверка 10 домашних заданий
  • Консультация с тренером 60 мин
89.99 $
Оформить подписку
Премиум
  • Все видеокурсы на 1 год
  • Тестирование по 24 курсам
  • Проверка 20 домашних заданий
  • Консультация с тренером 120 мин
169.99 $
Оформить подписку
комментарии и обсуждения
Notification success