Платформа.NET и язык программирования C# Основные конструкции и приемы.

Презентация:



Advertisements
Похожие презентации
Переменные и операторы УРОК 2. Переменные ПЕРЕМЕННАЯ – ?... контейнер для хранения данных. Переменная имеет имя – это….? последовательность букв, цифр.
Advertisements

Объектно-ориентированный язык программирования. Переменная - эта поименованная ячейка памяти, хранящая какое-либо одно значение (одно число, один фрагмент.
©ρŧą Базовые конструкции языка.
Тип, имя и значение переменной.. Переменные. В объектно-ориентированных языках программирования, и в частности в языке Visual Basic, переменные играют.
Лекция 4 Программирование на Паскале. Элементы языка Турбо Паскаль 7.0. Типы данных. Управляющие конструкции.
Министерство образования Республики Беларусь Белорусский государственный университет Управляющие структуры языков программирования.
Функции Функция – именованная последовательность описаний и операторов, выполняющая некоторое действие. Может иметь параметры и возвращать значение. Функция.
Практическое занятие 6. Функции. Большинство языков программирования используют понятия функции и процедуры. C++ формально не поддерживает понятие процедуры,
Статичні структури даних.. 2 Статические данные переменная (массив) имеет имя, по которому к ней можно обращаться размер заранее известен (задается при.
«Ветвление» в VB If условие Then Действия End If If условие Then Действия 1 Else Действия 2 End If.
Переменная - это величина, которая имеет имя, тип и значение. Значение переменной может меняться во время выполнения программы. В компьютерах каждая переменная.
Тема: Управление потоком в PHP Изучить возможности языка PHP при решении задач, требующих использования условного оператора. Рассмотреть примеры управления.
ОБЩИЕ СВЕДЕНИЯ О ЯЗЫКЕ ПРОГРАММИРОВАНИЯ ПАСКАЛЬ НАЧАЛА ПРОГРАММИРОВАНИЯ.
Работу выполнили ученицы 9 «Б» класса Гордеева Татьяна и Шебаршова Рита.
Тип, имя и значение переменной. В объектно-ориентированных языках программирования переменные играют такую же важную роль, как и в процедурных языках.
Разработка программного обеспечения для сигнальных процессоров TMS320C64xx в IDE Code Composer Studio Часть II. Язык программирования С. Основные понятия.
Элементы языка СИ Средства для написания простейших программ.
МАССИВЫ 4 Определение 4 Описание 4 Обращение к элементам массива 4 Связь массивов с указателями 4 Примеры программ.
turbo.exe основной файл среды Любой язык обладает алфавитом, синтаксисом и семантикой. В алфавит входит набор символов, использующихся в языке с помощью.
Основы ООП и C# Работа с объектами и классами. Классы Класс специальный тип данных для описания объектов. Он определяет данные и поведение типа. Определение.
Транксрипт:

Платформа.NET и язык программирования C# Основные конструкции и приемы

Платформа.NET.NET появилась в 2002 г. как инициативный проект фирмы Microsoft, включающий в себя комплекс технологий, программных средств, стандартов и средств разработки, направленный на обеспечение создания единого информационного пространства в Интернете и соединяющий или согласующий между собой современную вычислительную технику и программное обеспечение..NET имеет три прикладных направления: 1. Ориентированное на пользователей и разработчиков программных и технических средств. 2. Ориентированное на профессионалов-разработчиков информационных технологий. 3. Ориентированное на бизнесменов. Платформа.NET это совокупность программных средств, обеспечивающих разработку приложений на основе промежуточного кода и их выполнение в специализированной операционной среде.NET Framework.

Структура платформы.NET.NET состоит из пяти компонентов: Операционная система (Windows platform) Среда разработки Visual Studio.NET.NET Enterprise Servers.NET Framework.NET Building Block Services Visual Studio.NET среда разработки, делающая разработку приложений быстрой и приятной. В Visual Studio.NET входят средства разработки на языках C#, Visual Basic, Visual C++, а также ряд дополнительных технологий, облегчающих дизайн, коллективную разработку и внедрение Windows- приложений, web-приложений и web-сервисов..NET Enterprise Servers набор серверных продуктов, сокращающих время, требуемое для разработки крупномасштабных бизнес-систем. Сюда входят: сервер баз данных SQL Server, а также широкий ряд других серверных приложений Application Center, BizTalk Server, Commerce Server, Exchange Server, Host Integration Server, Internet Security Acceleration Server..NET Framework центральная часть платформы.NET. Она включает в себя общеязыковую среду выполнения Common Language Runtime ( CLR ) и общую структуру классов, которые могут использоваться всеми языками.NET. Среди библиотек классов.NET Framework есть практически все для разработки 90% типичных бизнес-приложений классы для разработки графических Windows- и web-приложений, классы для работы с базами данных и XML, и многое другое..NET Building Block Services строительные блоки для ваших приложений - веб сервисы. Windows platform самый нижний уровень, на котором работает все вышеперечисленное. Это операционная система, которая может быть одной из нескольких Windows-платформ, включая Windows Server 2013, Windows 7 и Windows 8.

Структура.NET Framework Common Language Runtime (CLR) Отладка, исключения, проверка типов, JIT-компиляторы Базовые классы среды Ввод/вывод, сеть, безопасность, строки, коллекции и т. д. Классы для работы с данными и XML ADO.NET, SQL, XML и т. д. Web ServicesWeb FormsWindows Forms

Промежуточный язык CIL (Common Intermediate Language) Любая программа, написанная на любом из языков программирования.NET компилируется в объектный код на промежуточном языке CIL (иначе IL или MSIL). В общем виде процесс компиляции выгляди так: 1. Имеем исходный текст на языке программирования (например, на Visual Basic.NET,, Visual С++.NET, Visual С#.NET или другом). 2. Компилятор проводит проверку синтаксиса исходного текста программы. 3. Затем программа перекомпилируется в код на промежуточном языке CIL. 4. С помощью синхронного JIT-компилятора программа с языка CIL окончательно компилируется в машинный код для конкретного процессора.

Пространство имен.NET Платформа.NET основана на использовании классов. Чтобы избежать пересечения имен классов.NET использует пространство имен. Пространство имен метод, который применяется для создания иерархической структуры всех классов с целью избежать ситуации пересечения имен классов. Допускается существование разных классов с одинаковыми именами, но только в разных пространствах имен. То есть пространство имен это область действия класса. Часто используемые пространства имен: Категория ИмяНазначение Базовое пространство имен.NET System Классы для обработка типов данных, исключительных ситуаций, сборки мусора и т. д.

Пространство имен.NET Категория ИмяНазначение Обычные задачиSystem.Collections System.IO System.Text Классы, поддерживающие коллекции объектов (массивы, словари и др.) Классы для чтения и записи данных из потоков и файлов Классы для работы с текстом и строками Графический интерфейс (GUI) System.Drawing System.Windows.Forms Классы для доступа к GDI (Graphic Dynamic Interface) и рисования двумерных картинок Классы для создания приложений Windows, которые используют интерфейс пользователя в стиле MS Windows

Пространство имен.NET Категория ИмяНазначение ДанныеSystem.Data System.XML Классы для доступа к базам данных источникам данных (ADO.NET) Классы для поддержки XML Сервисы средыSystem.Diagnostics System.Timers Классы для отладки приложений и отслеживания выполнения программ Классы для обработки событий таймера СетьSystem.Net Классы для обмена данными по компьютерным сетям с использованием различных протоколов

Интегрированная среда разработки Visual Studio.NET Настройка среды Выбор шаблона проекта Помощь в процессе разработки Отладка Компиляция готовой программы Создание дистрибутива программы

Основы C# Типы данных Переменные и константы Выражения и операторы Строки Методы Массивы Объекты и классы

Типы данных в C# Тип ОписаниеДиапазон Тип в CTS bool Логическийtrue или falseSystem.Boolean int4-байтовое целое число со знаком – … System.Int32 byte1-байтовое число 0…255System.Byte short2-байтовое целое число со знаком – … System.Int16 long8-байтовое целое число со знаком Примерно от –9*10Е18 до 9*10Е18 System.Int64

Типы данных в C# Тип ОписаниеДиапазон Тип в CTS double8-байтовое вещественное число Отрицательные: примерно от –1.79Е308 до –4.94Е–324 Положительные: примерно от 4.94Е–324 до 1.79Е308 System.Double float4-байтовое вещественное число Отрицательные: примерно от –3.40Е38 до –1.40Е–45 Положительные: примерно от 1.40Е–45 до 3.40Е38 System.Single char Символ в формате Unicode 0…65 535System.Char string СтрокаПримерно до 2 млн. символов System.String object ОбъектЛюбой объектSystem.Object

Числовые константы Разные типы числовых констант записываются по-разному. Тип int 125 (в десятеричной системе счисления) 0x7D или 0x7d (в шестнадцатеричной системе счисления) Тип long 125L или 125l Тип double – (обычная форма) – E2 или – e2 (показательная форма) Тип float – F или – f

Шестнадцатеричная система счисления Иногда удобно записывать числа в 16-ричной системе счисления. Таблица шестнадцатеричных цифр и их бинарные коды: Цифра КодЦифра КодЦифра КодЦифра Код C D A1010E B1011F1111 C67A 16 = В C# константы в 16-ричной системе счисления записывают при помощи этих 16 цифр с префиксом 0x Например, число, приведенное выше будет выглядеть так: 0xC67A

Переменные Переменная именованная область памяти. Имя переменной в С# может иметь до 255 символов (больших и маленьких букв, цифр). Предпочтительно начинать его с маленькой буквы и использовать систему "сamelCase". Например: myVeryImportantVariable Объявление переменной (явная типизация): тип_данных имя_переменой [ = начальное значение ]; Например: int maxNumber = 10; double radius ; Переменные одного типа модно объявить одной строкой: int m, l, k; Оператор присвоения значения переменной: имя_переменной = новое_значение; Например: lastName = "Иванов";

Константы Использование констант: Упрощается процесс внесения изменений в программу Упрощается чтение и понимание текста программы Константа хранит значение, присваиваемое ей в процессе компиляции программы и больше не меняется. Переменной значение присваивается в процессе выполнения программы. Объявление константы: const тип_данных имя_константы = значение_константы; Например: const double Pi = ; Множественное объявление: const string Mon = "понедельник", Tue = "вторник"; Далее ее можно использовать в коде: circLength = 2*Pi*radius; circSquare = Pi*radius*raduis; Констант у можно взять из класса System.Math : Math.Pi

Преобразование (конверсия) типов Неявная конверсия через операцию присваивания. Может вызвать ошибку, если возможна потеря информации. Явная конверсия: (имя_типа)имя_переменной При явной конверсии числа с плавающей точкой к целому типу происходит отбрасывание дробной части, а не округление. Для округления следует использовать функцию Math.Round(…) При конверсии не определяются диапазоны значений (по умолчанию). Чтобы диапазоны значений проверялись, код, содержащий конверсию следует заключить в блок checked { … //тут помещаем код }

Комментарии Комментарии экономят время написания, отладки и сопровождения программы. Они не обрабатываются компилятором и не занимают место в откомпилированной программе. Комментарии следует писать только в случае крайней необходимости. Лучше стремиться к такому стилю программирования, чтобы текст программы был понятным и само читаемым, что есть не требовал дополнительного комментирования. Комментировать следует сложные, неочевидные участки корда. В этом случае комментарии следует писать в процессе написания программы, а не оставлять комментирование на потом. Комментарии в C# записывают при помощи // в начале комментария. После // все символы до конца строки игнорируются компилятором. строка комментария // Скорость транспортного средства double v; комментарий в строке double v; // скорость транспортного средства Но лучше использовать значимое имя переменной: double vehicleVelocity; Чтобы закомментировать несколько строк, можно использовать скобки группового комментария : /* Несколько строк комментария */

Арифметические операции Операция ЗнакПример Примечание Сложение+x = a + b Вычитание–x = a – b Смена знака–x = –a Умножение*x = a * b Деление/x = a / b Для целых остаток отбрасывается Деление по модулю%x = a % b Остаток от деления целых чисел Постфиксный инкремент ++i++ Постфиксный декремент ––i –– Префиксный инкремент ++++I Префиксный декремент ––––i Приоритеты операций:.; (); ++, --; смена знака; * и /; + и – Операции присваивания: имя_переменной = значение; имя_переменной = значение; // знак бинарной операции например, x += 2; //вычисляем значение x+2 и запоминаем его в переменной x Присваивание имеет значение, равное значению присваиваемой величины.

Математические функции Для их использования следует использовать класс System.Math, например, y = Math.Sin(x); Модуль Abs(x) Знак числа Sign(x) Квадратный корень Sqrt(x) Тригонометрические функции Sin(x), Cos(x), Tan(x) Обратные тригонометрические функции Asin(x), Acos(x), Atan(x) Константы и е PI и E Экспонента и логарифмы Exp(x) e x, Log(x) lnx, Log10(x) log 10 x Максимум и минимум Max(x, y) ; Min(x, y) Округления Round(x) до ближайшего целого; Floor(x) до наибольшего целого, не превосходящего x; Ceiling(x) до наименьшего целого, большего или равного x Возведение в степень Pow(x, y) x y

Неявная типизация переменных При объявлении переменной можно явно не указывать ее тип: var имя_переменной = выражение; Компилятор вычислит тип автоматически по типу выражения, значение которого будет присвоено этой переменной.

Строковые операции и методы Операция Знак Конкатенация (слияние строк)+ Свойство Описание strX.Length Длина строки strX Метод Описание strX.IndexOf(strY) Возвращает позицию первого вхождения строки strY в строку strX strX.LastIndexOf(strY) Возвращает позицию последнего вхождения строки strY в строку strX strX.ToLower() Переводит все буквы строки strX в нижний регистр strX.ToUpper() Переводит все буквы строки strX верхний регистр strX.Substring(intStart, intCount) возвращает intCount символов строки strX с позиции intStart strX.Split(myChars) Разбивает строку strX на массив строк по разделителям из myChars (если myChars пустой или null, то разделитель пробел).

Перевод строки в число Неявное или явное преобразование типа string в числовые типы не работает. Для преобразования следует использовать один из двух способов: тип.Parse(выражение) Например: int.Parse(myString) или Convert.To СистемныйТип(выражение) Например: Convert.ToInt32(myString)

Метод string.Format Метод возвращает отформатированную по заданному формату строку. В качестве исходного материала для форматирования берется список данных. Использование: string.Format("строка с элементами форматирования {}", аргумент 1, …) Каждый элемент форматирования имеет вид: {индекс [, выравнивание][:строка_формата]} индекс определяет номер элемента последующего списка выравнивание целое со знаком, указывает желательную ширину поля форматирования строка_формата должна соответствовать типу форматируемого объекта Пример: string.Format("x = {0, 6:F4} y={1:G}", dblX, dblY) В методе Console.WriteLine(…); вызов string.Format можно опускать, оставляя только строку с элементами форматирования и список аргументов, например: Console.WriteLine(("x = {0, 6:F4} y={1:G}", dblX, dblY); Подробно о форматах можно прочитать в справочнике.

Методы Метод это последовательность операторов С#, оформленных заголовком и расположенных внутри фигурных скобок. Метод выполняет задачу и возвращает контроль в точку вызова, может возвращать или не возвращать значение. [модификаторы] возвр имя_метода ([ список_параметров ]) { … /операторы метода } Модификаторы пустой, public, private, static и т. п. (полный список в справке) Возвр это void (метод не возвращает значения) или тип возвращаемого значения. Список параметров идет через запятую. Каждый параметр может быть: 1.Обязательный: [ref|out] тип_параметра имя_параметра 2.Необязательный: [ref|out] тип_параметра имя_параметра = значение_по_умолчанию 3.Параметр, принимающий переменное количество аргументов: params [ref|out] тип[] имя_массива_параметров Сначала указываются все обязательные параметры, потом все необязательные, потом параметр с переменным количеством аргументов.

Методы (продолжение) Статический метод имеет модификатор static Вызов статического метода имя_класса.имя_метода ([список необходимых аргументов]) Например: int number = int.Parse(" "); double squareOfTriangle = a * b * Math.Sin(alpha); Console.Writeline("Hello!"); Если статический метод вызывается внутри класса, где он определен, имя класса можно опустить. Динамический метод не имеет модификатора static Вызов динамического метода имя_объекта.имя_метода([список аргументов]) Например: var str1 = "adcd"; var str2 = str1.ToUpper(); Досрочная остановка метода, не возвращающего значения, оператор return; Для возвращение значения следует использовать оператор return выражение; //тип выражения должен совпадать с типом в заголовке метода!!!

Перегрузки метода Перегрузки метода это несколько методов, имеющих одинаковое имя, но отличающихся друг от друга списком параметров (сигнатурой). Различие в сигнатурах может быть как по количеству параметров, так и по типам параметров. Документирование метода Можно документировать метод прямо в коде программы (Visual Studio). Для этого перед заголовком метода следует набрать строку комментария начинающегося с тройной косой черты и отредактировать появившийся шаблон подсказки: /// …

Область видимости переменной Это область кода программы, в пределах которой данная переменная доступна ("видна"). Место в коде программы, где объявлена переменная определяет ее область видимости. Грубо говоря, область видимости переменной это контент, внутри которого она объявлена. Тем самым область видимости может быть: 1. На уровне блока (внутри метода локальная переменная) 2. На уровне метода (локальная переменная) 3. На уровне класса (поле) Локальная переменная "перекрывает" статическое поле класса с тем же именем.

Джордж Буль ( ) No matter how correct a mathematical theorem may appear to be, one ought never to be satisfied that there was not something imperfect about it until it also gives the impression of being beautiful.

Таблицы истинности 0 false, 1 true 01 НЕ10 И ИЛИ ЛИБО Отрицание !x Конъюнкция x & y Дизъюнкция x | y Исключающая дизъюнкция x ^ y

Операторы сравнения Операторы сравнения позволяют сравнивать два значения любого типа. Результат получается типа bool ( true или false ). == равно != не равно > больше < меньше >= или равно <= меньше или равно

Логические операции Логические операции возвращают значение типа bool Логические операции над целыми числами производятся поразрядно в двоичном представлении числа: Операция Знак операции Пример Инверсия ~~x Конъюнкция& x & y Дизъюнкция | x | y Исключающая дизъюнкция ^ x ^ y Примечание. В C# есть еще две поразрядных операции: сдвиг влево x > y (сдвиг разрядов числа x на у позиций). Эти операции не относятся к логическим.

Логические операции (продолжение) Логические операции над операндами типа bool. Результат логической операции тоже имеет тип bool. Помимо &, | и ^ имеются Операция Знак операции Пример Отрицание !! (x > 0) Ленивая конъюнкция&& (x >= 3) && (x <= 7) В ленивой конъюнкции значение второго операнда не вычисляется, если значение первого операнда равно false. Ленивая дизъюнкция ||(x == 0 ) || (x == 1) В ленивой дизъюнкции значение второго операнда не вычисляется, если значение первого операнда равно true.

Операторы условия В C# два оператора условия if-else switch Управляющая структура if-else if (логическое_выражение) { … //операторы, которые выполняются, если выражение принимает значение true } [elseif (другое_логическое_выражение) { … // операторы, которые выполняются, если другое выражение принимает значение true }] … [else { … //операторы, которые выполняются если все предыдущие выражения принимают значение false }]

Операторы условия (продолжение) Управляющая структура switch switch (выражение) { [case метка 1: … //операторы, которые выполняются, если значение выражения равно метке 1 break;] [case метка 2: … //операторы, которые выполняются, если значение выражения равно метке 2 break;] … [default: … //операторы, которые выполняются, если значение выражения не равно ни одной из предыдущих меток break;] }

Операторы цикла Три вида циклов в C#: с определенным числом итераций цикл for с неопределенным числом итераций циклы while и do-while перебор элементов foreach Цикл for for (инициализвция_счетчика; условие; изменение_счетчика) { … [continue;] //Переход к следующей итерации цикла … [break;] //Досрочный выход из цикла … } Как правило, цикл for используется, когда заранее известно число итераций.

Операторы цикла (продолжение) Циклы while и do-while Используются, когда заранее неизвестно, сколько раз нужно выполнить тело цикла. while (условие) { … [continue;] //Переход к следующей итерации … [break;] //Выход из цикла … } do { … [continue;] //Переход к следующей итерации … [break;] // Выход из цикла … } while (условие); while возможно не будет выполнено ни одной итерации do-while будет выполнена как минимум одна итерация Обратите внимание на необходимость знака " ; " в конце во втором случае!!!

Ошибки 1. Ошибки компиляции 2. Ошибки выполнения 3. Логические ошибки 4. Ошибки алгоритмов

Обработка исключений Ошибка при выполнении называется исключительной ситуацией (исключением). С целью обезопасить программу от предполагаемых исключений используют структуру try … catch … finally : try { … //Потенциально опасный код } catch [фильтр] { … //Код, выполняемый при возникновении исключения, //если значение фильтра true } [дополнительные блоки catch] //Можно обрабатывать другие исключения [finally { … //Код, выполняемый всегда после блоков try и catch }]

Массивы Массив упорядоченная совокупность однотипных данных. Массив обязательно имеет имя. Каждый элемент массива имеет уникальный индекс. Нумерация элементов массива начинается с нуля. Объявление массива: тип[] имя_массива; Например: int[] array; //объявили массив целых чисел Инициализация массива: имя_массива = new тип[число_элементов_массива]; Например, array = new int[3]; //иницализировали массив из трех целых чисел Присвоение значения элементу массива: имя_массива[индекс_элемента] = значение_элемента; Например: array[0] = 18; array[1] = -2; array[2] = 0;

Массивы (продолжение) Цикл foreach foreach (переменная in имя массива) { … //тело цикла } Короткая форма записи массива { элемент 0, элемент 1, …, элементN } Например, при инициализации записать int array = new int[] {1, 2, 3, 4, 5};

Тип-значение и ссылочный тип Тип-значение Ссылочный тип Объект хранится там, где он объявлен. Объект хранится в куче. В месте, где объект объявлен, стоит ссылка на него. Не может иметь значение null.Может иметь значение null. Заранее известно, сколько памяти он займет. Заранее может быть неизвестно, сколько памяти он займет. Объект удаляется вместе с контентом, в котором он хранится. Объект удаляется сборщиком мусора после того, как на объект не будет ни одной актуальной ссылки. Равенство объектов это равенство значений Равенство объектов это совпадение ссылок (если для типа операция сравнения не переопределена, как, например, в типе string).

Многомерные массивы тип[, (…,)] имя_массива; имя_массива = new тип[длина 1, …, длинаN]; Например, int[, ] matrix = new int[2,3]; // задает и инициализирует двумерный // массив размеров 2 х 3 Полезно знать методы и свойства: GetLength(i) число элементов по i-му измерению Length общее число элементов Rank число измерений

Визуализация двумерного массива: таблицы (матрицы) массив array[2,3] Двумерный массив представляет собой матрицу или таблицу данных Он индексируется переменными row и column как array[row,column] Первая координата массива изменяется по вертикали array[0, 0]array[0, 1]array[0, 2] array[1, 0]array[1, 1]array[1, 2]

Визуализация двумерного массива: изображения array[0, 0]array[1, 0]array[2, 0] array[0, 1]array[1, 1]array[2, 1] массив array[3,2] Двумерный массив представляет собой изображение Он индексируется переменными x и y как array[x, y] Первая координата массива изменяется по горизонтали

Массивы массивов Объявление массива массивов: тип[][] имя_массива; Например: int[][] array; //объявили массив целочисленных массивов Инициализация массива массивов: имя_массива = new тип[число_элементов_массива][]; Например, array = new int[3] [];//иницализировали массив из трех целых чисел Инициализация элемента массива массивов: имя_массива[индекс] = new тип[число_элементов]; Обращение к элементу массива массивов: имя_массива[индекс_внешн][индекс_внутр] = значение;

Рефакторинг Рефакторинг это изменение кода программы без изменения ее функциональности с целью улучшения читаемости кода, повышения ясности структуры кода и его эстетического восприятия и т. п. Один из основных принципов создания программы code and refact. Некоторые основные принципы рефакторинга: 1. Правильное именование: имена переменных принято начинать с маленькой буквы; имена методов, классов, констант принято начинать с большой буквы; имена по возможности должны быть осмысленными; используйте camelCase. 2. При необходимости используйте именованные константы и перечисления. 3. Используйте выделение метода: если есть повторяемость кода (принцип don't repeat yourself); если метод слишком громоздкий, его целесообразно разбить на более простые методы.

Перечисления Перечисление это пользовательский тип данных, представляющий собой набор имен, определяющий все возможные целочисленные значения, которые могут быть назначены переменной этого типа. Перечисление задается следующим образом: [модификатор] enum имя_перечисления { имя 1 [= значение 1], имя 2 [= значение 2], … имяN [= значениеN] } Если значения не заданы, то именам в списке присваиваются значения по умолчанию 0, 1, 2, …. Например, enum SimpleColor {Black, White, Gray} задает значения 0 для Black, 1 для White, 2 для Gray.