- •1. Лекция: Visual Studio .Net, Framework .Net
- •Visual Studio .Net - открытая среда разработки
- •Открытость
- •Framework .Net - единый каркас среды разработки
- •Библиотека классов FCL - статический компонент каркаса
- •Единство каркаса
- •Встроенные примитивные типы
- •Структурные типы
- •Архитектура приложений
- •Модульность
- •Общеязыковая исполнительная среда CLR - динамический компонент каркаса
- •Двухэтапная компиляция. Управляемый модуль и управляемый код
- •Виртуальная машина
- •Дизассемблер и ассемблер
- •Метаданные
- •Сборщик мусора - Garbage Collector - и управление памятью
- •Исключительные ситуации
- •События
- •Общие спецификации и совместимые модули
- •2. Лекция: Язык C# и первые проекты
- •Создание C#
- •Виды проектов
- •Консольный проект
- •Windows-проект
- •Начало начал - точка "большого взрыва"
- •Выполнение проекта по умолчанию после "большого взрыва"
- •Проект WindowsHello
- •3. Лекция: Система типов языка С#
- •Общий взгляд
- •Система типов
- •Типы или классы? И типы, и классы
- •Семантика присваивания
- •Преобразование к типу object
- •Примеры преобразований
- •Семантика присваивания. Преобразования между ссылочными и значимыми типами
- •Операции "упаковать" и "распаковать" (boxing и unboxing).
- •4. Лекция: Преобразования типов
- •Где, как и когда выполняются преобразования типов?
- •Преобразования ссылочных типов
- •Преобразования типов в выражениях
- •Преобразования внутри арифметического типа
- •Явные преобразования
- •Преобразования строкового типа
- •Преобразования и класс Convert
- •Проверяемые преобразования
- •Исключения и охраняемые блоки. Первое знакомство
- •Опасные вычисления в охраняемых проверяемых блоках
- •Опасные вычисления в охраняемых непроверяемых блоках
- •Опасные преобразования и методы класса Convert
- •5. Лекция: Переменные и выражения
- •Объявление переменных
- •Проект Variables
- •Синтаксис объявления
- •Время жизни и область видимости переменных
- •Поля
- •Локальные переменные
- •Глобальные переменные уровня процедуры. Существуют ли?
- •Константы
- •6. Лекция: Выражения. Операции в выражениях
- •Выражения
- •Приоритет и порядок выполнения операций
- •Перегрузка операций
- •С чего начинается выполнение выражения
- •Операции "увеличить" и "уменьшить" (increment, decrement)
- •Операции sizeof и typeof
- •Как получить подробную информацию о классе?
- •Статические поля и методы арифметических классов
- •Операция new
- •Арифметические операции
- •Операции отношения
- •Операции проверки типов
- •Операции сдвига
- •Логические операции
- •Условное выражение
- •Операция приведения к типу
- •7. Лекция: Присваивание и встроенные функции
- •Присваивание
- •Специальные случаи присваивания
- •Определенное присваивание
- •Еще раз о семантике присваивания
- •Рассмотрим объявления:
- •Класс Math и его функции
- •Класс Random и его функции
- •8. Лекция: Операторы языка C#
- •Операторы языка C#
- •Оператор присваивания
- •Блок или составной оператор
- •Пустой оператор
- •Операторы выбора
- •Оператор if
- •Оператор switch
- •Операторы перехода
- •Оператор goto
- •Операторы break и continue
- •Оператор return
- •Операторы цикла
- •Оператор for
- •Циклы While
- •Цикл foreach
- •9. Лекция: Процедуры и функции - методы класса
- •Процедуры и функции - функциональные модули
- •Процедуры и функции - методы класса
- •Процедуры и функции. Отличия
- •Описание методов (процедур и функций). Синтаксис
- •Список формальных аргументов
- •Тело метода
- •Вызов метода. Синтаксис
- •О соответствии списков формальных и фактических аргументов
- •Вызов метода. Семантика
- •Что нужно знать о методах?
- •Почему у методов мало аргументов?
- •Поля класса или функции без аргументов?
- •Пример: две версии класса Account
- •Функции с побочным эффектом
- •Методы. Перегрузка
- •10. Лекция: Корректность методов. Рекурсия
- •Корректность методов
- •Инварианты и варианты цикла
- •Рекурсия
- •Рекурсивное решение задачи "Ханойские башни"
- •Быстрая сортировка Хоара
- •11. Лекция: Массивы языка C#
- •Общий взгляд
- •Объявление массивов
- •Объявление одномерных массивов
- •Динамические массивы
- •Многомерные массивы
- •Массивы массивов
- •Процедуры и массивы
- •12. Лекция: Класс Array и новые возможности массивов
- •Класс Array
- •Массивы как коллекции
- •Сортировка и поиск. Статические методы класса Array
- •Класс Object и массивы
- •Массивы объектов
- •Массивы. Семантика присваивания
- •13. Лекция: Символы и строки постоянной длины в C#
- •Общий взгляд
- •Строки С++
- •Строки С#
- •Класс char
- •Класс char[] - массив символов
- •Существует ли в C# тип char*
- •14. Лекция: Строки C#. Классы String и StringBuilder
- •Класс String
- •Объявление строк. Конструкторы класса string
- •Операции над строками
- •Строковые константы
- •Неизменяемый класс string
- •Статические свойства и методы класса String
- •Метод Format
- •Методы Join и Split
- •Динамические методы класса String
- •Класс StringBuilder - построитель строк
- •Объявление строк. Конструкторы класса StringBuilder
- •Операции над строками
- •Основные методы
- •Емкость буфера
- •15. Лекция: Регулярные выражения
- •Пространство имен RegularExpression и классы регулярных выражений
- •Немного теории
- •Синтаксис регулярных выражений
- •Классы Group и GroupCollection
- •Классы Capture и CaptureCollection
- •Перечисление RegexOptions
- •Класс RegexCompilationInfo
- •Примеры работы с регулярными выражениями
- •Пример "чет и нечет"
- •Пример "око и рококо"
- •Пример "кок и кук"
- •Пример "обратные ссылки"
- •Пример "Дом Джека"
- •Пример "Атрибуты"
- •16. Лекция: Классы
- •Классы и ООП
- •Две роли классов
- •Синтаксис класса
- •Поля класса
- •Доступ к полям
- •Методы класса
- •Доступ к методам
- •Методы-свойства
- •Индексаторы
- •Операции
- •Статические поля и методы класса
- •Константы
- •Конструкторы класса
- •Деструкторы класса
- •Проектирование класса Rational
- •Свойства класса Rational
- •Конструкторы класса Rational
- •Методы класса Rational
- •Закрытый метод НОД
- •Печать рациональных чисел
- •Тестирование создания рациональных чисел
- •Операции над рациональными числами
- •Константы класса Rational
- •17. Лекция: Структуры и перечисления
- •Развернутые и ссылочные типы
- •Классы и структуры
- •Структуры
- •Синтаксис структур
- •Класс Rational или структура Rational
- •Встроенные структуры
- •Еще раз о двух семантиках присваивания
- •Перечисления
- •Персоны и профессии
- •18. Лекция: Отношения между классами. Клиенты и наследники
- •Отношения между классами
- •Отношения "является" и "имеет"
- •Отношение вложенности
- •Расширение определения клиента класса
- •Отношения между клиентами и поставщиками
- •Сам себе клиент
- •Наследование
- •Добавление полей потомком
- •Конструкторы родителей и потомков
- •Добавление методов и изменение методов родителя
- •Статический контроль типов и динамическое связывание
- •Три механизма, обеспечивающие полиморфизм
- •Пример работы с полиморфным семейством классов
- •Абстрактные классы
- •Классы без потомков
- •19. Лекция: Интерфейсы. Множественное наследование
- •Интерфейсы
- •Две стратегии реализации интерфейса
- •Преобразование к классу интерфейса
- •Проблемы множественного наследования
- •Коллизия имен
- •Наследование от общего предка
- •Встроенные интерфейсы
- •Упорядоченность объектов и интерфейс IComparable
- •Клонирование и интерфейс ICloneable
- •Сериализация объектов
- •Класс с атрибутом сериализации
- •Интерфейс ISerializable
- •20. Лекция: Функциональный тип в C#. Делегаты
- •Как определяется функциональный тип и как появляются его экземпляры
- •Функции высших порядков
- •Вычисление интеграла
- •Построение программных систем методом "раскрутки". Функции обратного вызова
- •Наследование и полиморфизм - альтернатива обратному вызову
- •Делегаты как свойства
- •Операции над делегатами. Класс Delegate
- •Операции "+" и "-"
- •Пример "Комбинирование делегатов"
- •Пример "Плохая служба"
- •21. Лекция: События
- •Классы с событиями
- •Класс sender. Как объявляются события?
- •Делегаты и события
- •Как зажигаются события
- •Классы receiver. Как обрабатываются события
- •Классы с событиями, допустимые в каркасе .Net Framework
- •Пример "Списки с событиями"
- •Класс sender
- •Классы receiver
- •Две проблемы с обработчиками событий
- •Игнорирование коллег
- •Переопределение значений аргументов события
- •Классы с большим числом событий
- •Проект "Город и его службы"
- •22. Лекция: Универсальность. Классы с родовыми параметрами
- •Наследование и универсальность
- •Синтаксис универсального класса
- •Класс с универсальными методами
- •Два основных механизма объектной технологии
- •Стек. От абстрактного, универсального класса к конкретным версиям
- •Ограниченная универсальность
- •Синтаксис ограничений
- •Список с возможностью поиска элементов по ключу
- •Как справиться с арифметикой
- •Родовое порождение класса. Предложение using
- •Универсальность и специальные случаи классов
- •Универсальные структуры
- •Универсальные интерфейсы
- •Универсальные делегаты
- •Framework .Net и универсальность
- •23. Лекция: Отладка и обработка исключительных ситуаций
- •Корректность и устойчивость программных систем
- •Жизненный цикл программной системы
- •Три закона программотехники
- •Первый закон (закон для разработчика)
- •Второй закон (закон для пользователя)
- •Третий закон (закон чечако)
- •Отладка
- •Создание надежного кода
- •Искусство отладки
- •Отладочная печать и условная компиляция
- •Классы Debug и Trace
- •Метод Флойда и утверждения Assert
- •Классы StackTrace и BooleanSwitch
- •Отладка и инструментальная среда Visual Studio .Net
- •Обработка исключительных ситуаций
- •Обработка исключений в языках C/C++
- •Схема обработки исключений в C#
- •Выбрасывание исключений. Создание объектов Exception
- •Захват исключения
- •Параллельная работа обработчиков исключений
- •Блок finally
- •Схема Бертрана обработки исключительных ситуаций
- •Класс Exception
- •Организация интерфейса
- •Форма и элементы управления
- •Взаимодействие форм
- •Модальные и немодальные формы
- •Передача информации между формами
- •Образцы форм
- •Главная кнопочная форма
- •Шаблон формы для работы с классом
- •Работа со списками (еще один шаблон)
- •Элемент управления класса ListBox
- •Наследование форм
- •Два наследника формы TwoLists
- •Огранизация меню в формах
- •Создание меню в режиме проектирования
- •Классы меню
- •Создание инструментальной панели с командными кнопками
- •Рисование в форме
- •Класс Graphics
- •Методы класса Graphics
- •Класс Pen
- •Класс Brush
- •Проект "Паутина Безье, кисти и краски"
- •Паутина Безье
- •Событие Paint
- •Кисти и краски
- •Абстрактный класс Figure
- •Классы семейства геометрических фигур
- •Класс Ellipse
- •Класс Circle
- •Класс LittleCircle
- •Класс Rect
- •Класс Square
- •Класс Person
- •Список с курсором. Динамические структуры данных
- •Классы элементов списка
- •Организация интерфейса
для несовпадающих символов выдает "расстояние" между символами в соответствии с их упорядоченностью в кодировке Unicode. Приведу пример:
public void testCompareChars()
{
char ch1, ch2; int dif;
Console.WriteLine("Метод CompareTo"); ch1='A'; ch2= 'Z';
dif = ch1.CompareTo(ch2); Console.WriteLine("Расстояние между символами {0},
{1} = {2}", ch1, ch2, dif); ch1='а'; ch2= 'А';
dif = ch1.CompareTo(ch2); Console.WriteLine("Расстояние между символами {0},
{1} = {2}", ch1, ch2, dif); ch1='Я'; ch2= 'А';
dif = ch1.CompareTo(ch2); Console.WriteLine("Расстояние между символами {0},
{1} = {2}", ch1, ch2, dif); ch1='A'; ch2= 'A';
dif = ch1.CompareTo(ch2); Console.WriteLine("Расстояние между символами {0},
{1} = {2}", ch1, ch2, dif); ch1='А'; ch2= 'A';
dif = ch1.CompareTo(ch2); Console.WriteLine("Расстояние между символами {0},
{1} = {2}", ch1, ch2, dif); ch1='Ё'; ch2= 'А';
dif = ch1.CompareTo(ch2); Console.WriteLine("Расстояние между символами {0},
{1} = {2}", ch1, ch2, dif); }//TestCompareChars
Результаты сравнения изображены на рис. 13.2.
Рис. 13.2. Сравнение символов
Анализируя эти результаты, можно понять, что в кодировке Unicode как латиница, так и кириллица плотно упакованы. Исключение составляет буква Ё - заглавная и малая - они выпадают из плотной кодировки. Малые буквы в кодировке непосредственно следуют за заглавными буквами. Расстояние между алфавитами в кодировке довольно большое - русская буква А на 975 символов правее в кодировке, чем соответствующая буква в латинском алфавите.
Класс char[] - массив символов
В языке C# определен класс Char[], и его можно использовать для представления строк постоянной длины, как это делается в С++. Более того, поскольку массивы в C# динамические, то расширяется класс задач, в которых можно использовать массивы символов для представления строк. Так что имеет смысл разобраться, насколько хорошо C# поддерживает работу с таким представлением строк.
Прежде всего, ответим на вопрос, задает ли массив символов C# строку С, заканчивающуюся нулем? Ответ: нет, не задает. Массив char[] - это обычный массив. Более того, его нельзя инициализировать строкой символов, как это разрешается в С++. Константа, задающая строку символов, принадлежит классу String, а в C# не определены взаимные преобразования между классами String и Char[], даже явные. У класса String есть, правда, динамический метод ToCharArray, задающий подобное преобразование. Возможно также посимвольно передать содержимое переменной string в массив символов. Приведу пример:
public void TestCharArAndString()
{
//массивы символов
//char[] strM1 = "Hello, World!";
//ошибка: нет преобразования класса string в класс char[] string hello = "Здравствуй, Мир!";
char[] strM1 = hello.ToCharArray(); PrintCharAr("strM1",strM1); //копирование подстроки
char[] World = new char[3]; Array.Copy(strM1,12,World,0,3); PrintCharAr("World",World); Console.WriteLine(CharArrayToString(World));
}//TestCharArAndString
Закомментированные операторы в начале этой процедуры показывают, что прямое присваивание строки массиву символов недопустимо. Однако метод ToCharArray, которым обладают строки, позволяет легко преодолеть эту трудность. Еще одну возможность преобразования строки в массив символов предоставляет статический метод Copy класса Array.
В нашем примере часть строки strM1 копируется в массив World. По ходу дела в методе вызывается процедура PrintCharAr класса Testing, печатающая массив символов как строку. Вот ее текст:
void PrintCharAr(string name,char[] ar)
{
Console.WriteLine(name); for(int i=0; i < ar.Length; i++)
Console.Write(ar[i]);
Console.WriteLine();
}//PrintCharAr
Метод ToCharArray позволяет преобразовать строку в массив символов. К сожалению, обратная операция не определена, поскольку метод ToString, которым, конечно же, обладают все объекты класса Char[], печатает информацию о классе, а не содержимое массива. Ситуацию легко исправить, написав подходящую процедуру. Вот текст этой процедуры CharArrayToString, вызываемой в нашем тестирующем примере:
string CharArrayToString(char[] ar)
{
string result="";
for(int i = 0; i< ar.Length; i++) result += ar[i]; return(result);
}//CharArrayToString
Класс Char[], как и всякий класс-массив в C#, является наследником не только класса Object, но и класса Array, и, следовательно, обладает всеми методами родительских классов, подробно рассмотренных в предыдущей главе. А есть ли у него специфические методы, которые позволяют выполнять операции над строками,
представленными массивами символов? Таких специальных операций нет. Но некоторые перегруженные методы класса Array можно рассматривать как операции над строками. Например, метод Copy дает возможность выделять и заменять подстроку в теле строки. Методы IndexOf, LastIndexOf позволяют определить индексы первого и последнего вхождения в строку некоторого символа. К сожалению, их нельзя использовать для более интересной операции - нахождения индекса вхождения подстроки в строку. При необходимости такую процедуру можно написать самому. Вот как она выглядит:
int IndexOfStr( char[]s1, char[] s2)
{
//возвращает индекс первого вхождения подстроки s2 в //строку s1
int i =0, j=0, n=s1.Length-s2.Length; bool found = false; while( (i<=n) && !found)
{
j = Array.IndexOf(s1,s2[0],i); if (j <= n)
{
found=true; int k = 0;
while ((k < s2.Length)&& found)
{
found =char.Equals(s1[k+j],s2[k]); k++;
}
}
i=j+1;
}
if(found) return(j); else return(-1); }//IndexOfStr
В реализации используется метод IndexOf класса Array, позволяющий найти начало совпадения строк, после чего проверяется совпадение остальных символов. Реализованный здесь алгоритм является самым очевидным, но далеко не самым эффективным.
Атеперь рассмотрим процедуру, в которой определяются индексы вхождения символов
иподстрок в строку:
public void TestIndexSym()
{
char[] str1, str2;
str1 = "рококо".ToCharArray(); //определение вхождения символа int find, lind;
find= Array.IndexOf(str1,'о'); lind = Array.LastIndexOf(str1,'о');
Console.WriteLine("Индексы вхождения о в рококо:{0},{1}; ", find, lind);
//определение вхождения подстроки str2 = "рок".ToCharArray();
find = IndexOfStr(str1,str2); Console.WriteLine("Индекс первого вхождения рок в
рококо:{0}", find); str2 = "око".ToCharArray();
find = IndexOfStr(str1,str2); Console.WriteLine("Индекс первого вхождения око в
рококо:{0}", find); }//TestIndexSym
В этой процедуре вначале используются стандартные методы класса Array для определения индексов вхождения символа в строку, а затем созданный метод
IndexOfStr для определения индекса первого вхождения подстроки. Корректность работы метода проверяется на разных строках. Вот результаты ее работы.
Рис. 13.3. Индексы вхождения подстроки в строку
Существует ли в C# тип char*
В языке C# указатели допускаются в блоках, отмеченных как небезопасные. Теоретически в таких блоках можно объявить переменную типа Char*, но все равно не удастся написать столь же короткую, как в С++, процедуру копирования строк. Правильно считать, что в C# строки типа char* использовать не рекомендуется.