
- •1. Лекция: Visual Studio .Net, Framework .Net
- •Открытость
- •Модульность
- •Виртуальная машина
- •Дизассемблер и ассемблер
- •Метаданные
- •Сборщик мусора - Garbage Collector - и управление памятью
- •Исключительные ситуации
- •События
- •Общие спецификации и совместимые модули
- •2. Лекция: Язык c# и первые проекты
- •Создание c#
- •Виды проектов
- •Консольный проект
- •Windows-проект
- •Начало начал - точка "большого взрыва"
- •Выполнение проекта по умолчанию после "большого взрыва"
- •Проект WindowsHello
- •Общий взгляд
- •Система типов
- •Типы или классы? и типы, и классы
- •Семантика присваивания
- •Преобразование к типу object
- •Примеры преобразований
- •Семантика присваивания. Преобразования между ссылочными и значимыми типами
- •Операции "упаковать" и "распаковать" (boxing и unboxing).
- •4. Лекция: Преобразования типов
- •Где, как и когда выполняются преобразования типов?
- •Преобразования ссылочных типов
- •Преобразования типов в выражениях
- •Преобразования внутри арифметического типа
- •Преобразования и класс Convert
- •Проверяемые преобразования
- •Исключения и охраняемые блоки. Первое знакомство
- •Опасные вычисления в охраняемых проверяемых блоках
- •Опасные вычисления в охраняемых непроверяемых блоках
- •Опасные преобразования и методы класса Convert
- •5. Лекция: Переменные и выражения
- •Объявление переменных
- •Время жизни и область видимости переменных
- •Глобальные переменные уровня модуля. Существуют ли они в c#?
- •Int X,y; //координаты точки
- •Локальные переменные
- •Глобальные переменные уровня процедуры. Существуют ли?
- •Константы
- •Выражения
- •Приоритет и порядок выполнения операций
- •Перегрузка операций
- •Операции sizeof и typeof
- •Как получить подробную информацию о классе?
- •Статические поля и методы арифметических классов
- •Логические операции
- •Условное выражение
- •Операция приведения к типу
- •Присваивание
- •Специальные случаи присваивания
- •Определенное присваивание
- •Еще раз о семантике присваивания
- •Рассмотрим объявления:
- •Класс Math и его функции
- •Класс Random и его функции
- •Блок или составной оператор
- •If(выражение_1) оператор_1
- •If(выражение1) if(выражение2) if(выражение3) ...
- •Оператор switch
- •Операторы break и continue
- •Циклы While
- •Цикл foreach
- •Процедуры и функции - функциональные модули
- •Процедуры и функции - методы класса
- •Процедуры и функции. Отличия
- •Описание методов (процедур и функций). Синтаксис
- •Список формальных аргументов
- •Тело метода
- •Вызов метода. Синтаксис
- •О соответствии списков формальных и фактических аргументов
- •Вызов метода. Семантика
- •Поля класса или функции без аргументов?
- •Пример: две версии класса Account
- •Функции с побочным эффектом
- •Методы. Перегрузка
- •10. Лекция: Корректность методов. Рекурсия
- •Корректность методов
- •Инварианты и варианты цикла
- •Рекурсия
- •Рекурсивное решение задачи "Ханойские башни"
- •Быстрая сортировка Хоара
- •11. Лекция: Массивы языка c#
- •Общий взгляд
- •Динамические массивы
- •Многомерные массивы
- •Массивы массивов
- •Процедуры и массивы
- •Класс Array
- •Массивы как коллекции
- •Сортировка и поиск. Статические методы класса Array
- •Сводка свойств и методов класса Array
- •Класс Object и массивы
- •Массивы объектов
- •Массивы. Семантика присваивания
- •Общий взгляд
- •Класс char[] - массив символов
- •Операции над строками
- •Строковые константы
- •Неизменяемый класс string
- •Статические свойства и методы класса String
- •Метод Format
- •Методы Join и Split
- •Динамические методы класса String
- •Операции над строками
- •Основные методы
- •Емкость буфера
- •Пространство имен RegularExpression и классы регулярных выражений
- •Немного теории
- •Синтаксис регулярных выражений
- •Классы Match и MatchCollection
- •Классы Group и GroupCollection
- •Пример "чет и нечет"
- •Пример "око и рококо"
- •Пример "кок и кук"
- •Пример "обратные ссылки"
- •Пример "Дом Джека"
- •Пример "Атрибуты"
- •16. Лекция: Классы
- •Синтаксис класса
- •Поля класса
- •Доступ к полям
- •Методы-свойства
- •Индексаторы
- •Константы
- •Конструкторы класса
- •Деструкторы класса
- •Проектирование класса Rational
- •Методы класса Rational
- •Закрытый метод нод
- •Операции над рациональными числами
- •Константы класса Rational
- •Развернутые и ссылочные типы
- •Классы и структуры
- •Класс Rational или структура Rational
- •Встроенные структуры
- •Еще раз о двух семантиках присваивания
- •Перечисления
- •Персоны и профессии
- •18. Лекция: Отношения между классами. Клиенты и наследники
- •Отношения между классами
- •Отношения "является" и "имеет"
- •Отношение вложенности
- •Расширение определения клиента класса
- •Отношения между клиентами и поставщиками
- •Сам себе клиент
- •Наследование
- •Добавление полей потомком
- •Конструкторы родителей и потомков
- •Добавление методов и изменение методов родителя
- •Статический контроль типов и динамическое связывание
- •Три механизма, обеспечивающие полиморфизм
- •Пример работы с полиморфным семейством классов
- •Абстрактные классы
- •Классы без потомков
- •Преобразование к классу интерфейса
- •Наследование от общего предка
- •Клонирование и интерфейс iCloneable
- •Сериализация объектов
- •Класс с атрибутом сериализации
- •Интерфейс iSerializable
- •20. Лекция: Функциональный тип в c#. Делегаты
- •Как определяется функциональный тип и как появляются его экземпляры
- •Функции высших порядков
- •Вычисление интеграла
- •Построение программных систем методом "раскрутки". Функции обратного вызова
- •Наследование и полиморфизм - альтернатива обратному вызову
- •Делегаты как свойства
- •Операции над делегатами. Класс Delegate
- •Пример "Плохая служба"
- •21. Лекция: События
- •Классы с событиями
- •Класс sender. Как объявляются события?
- •Делегаты и события
- •Как зажигаются события
- •Классы receiver. Как обрабатываются события
- •Классы с событиями, допустимые в каркасе .Net Framework
- •Пример "Списки с событиями"
- •Класс sender
- •Классы receiver
- •Переопределение значений аргументов события
- •Классы с большим числом событий
- •Проект "Город и его службы"
- •22. Лекция: Универсальность. Классы с родовыми параметрами
- •Наследование и универсальность
- •Синтаксис универсального класса
- •Класс с универсальными методами
- •Два основных механизма объектной технологии
- •Стек. От абстрактного, универсального класса к конкретным версиям
- •Ограниченная универсальность
- •Синтаксис ограничений
- •Список с возможностью поиска элементов по ключу
- •Как справиться с арифметикой
- •Родовое порождение класса. Предложение using
- •Универсальные делегаты
- •Framework .Net и универсальность
- •23. Лекция: Отладка и обработка исключительных ситуаций
- •Корректность и устойчивость программных систем
- •Жизненный цикл программной системы
- •Искусство отладки
- •Отладочная печать и условная компиляция
- •Классы Debug и Trace
- •Метод Флойда и утверждения Assert
- •Выбрасывание исключений. Создание объектов Exception
- •If !MyMethod(){// обработка ошибки}
- •Параллельная работа обработчиков исключений
- •Блок finally
- •Класс Exception
- •Организация интерфейса
- •Форма и элементы управления
- •Взаимодействие форм
- •Модальные и немодальные формы
- •Передача информации между формами
- •Шаблон формы для работы с классом
- •Наследование форм
- •Два наследника формы TwoLists
- •Огранизация меню в формах
- •Создание меню в режиме проектирования
- •Классы меню
- •Создание инструментальной панели с командными кнопками
- •Методы класса Graphics
- •Класс Pen
- •Класс Brush
- •Событие Paint
- •Кисти и краски
- •25. Лекция: Финальный проект
- •Абстрактный класс Figure
- •Класс Circle
- •Список с курсором. Динамические структуры данных
- •Классы элементов списка
- •Организация интерфейса
Универсальные делегаты
Делегаты также могут иметь родовые параметры. Чаще встречается ситуация, когда делегат объявляется в универсальном классе и использует в своем объявлении параметры универсального класса. Давайте рассмотрим ситуацию с делегатами более подробно. Вот объявление универсального класса, не очень удачно названного Delegate, в котором объявляется функциональный тип - delegate:
class Delegate<T>
{
public delegate T Del(T a, T b);
}
Как видите, тип аргументов и возвращаемого значения в сигнатуре функционального типа определяется классом Delegate.
Добавим в класс функцию высшего порядка FunAr, одним из аргументов которой будет функция типа Del, заданного делегатом. Эта функция будет применяться к элементам массива, передаваемого также функции FunAr. Приведу описание:
public T FunAr(T[] arr, T a0, Del f)
{
T temp = a0;
for(int i =0; i<arr.Length; i++)
{
temp = f(temp, arr[i]);
}
return (temp);
}
Эта универсальная функция с успехом может применяться для вычисления сумм, произведения, минимума и других подобных характеристик массива.
Рассмотрим теперь клиентский класс Testing, в котором определен набор функций:
public int max2(int a, int b)
{ return (a > b) ? a : b; }
public double min2(double a, double b)
{ return (a < b) ? a : b; }
public string sum2(string a, string b)
{ return a + b; }
public float prod2(float a, float b)
{ return a * b; }
Хотя все функции имеют разные типы, все они соответствуют определению класса Del - имеют два аргумента одного типа и возвращают результат того же типа. Посмотрим, как они применяются в тестирующем методе класса Testing:
public void TestFun()
{
int[] ar1 = { 3, 5, 7, 9 };
double[] ar2 = { 3.5, 5.7, 7.9 };
string[] ar3 = { "Мама ", "мыла ", "Машу ", "мылом." };
float[] ar4 = { 5f, 7f, 9f, 11f };
Delegate<int> d1 = new Delegate<int>();
Delegate<int>.Del del1;
del1= this.max2;
int max = d1.FunAr(ar1, ar1[0], del1);
Console.WriteLine("max= {0}", max);
Delegate<double> d2 = new Delegate<double>();
Delegate<double>.Del del2;
del2 = this.min2;
double min = d2.FunAr(ar2, ar2[0], del2);
Console.WriteLine("min= {0}", min);
Delegate<string> d3 = new Delegate<string>();
Delegate<string>.Del del3;
del3 = this.sum2;
string sum = d3.FunAr(ar3, "", del3);
Console.WriteLine("concat= {0}", sum);
Delegate<float> d4 = new Delegate<float>();
Delegate<float>.Del del4;
del4 = this.prod2;
float prod = d4.FunAr(ar4, 1f, del4);
Console.WriteLine("prod= {0}", prod);
}
Обратите внимание на объявление экземпляра делегата:
Delegate<int>.Del del1;
В момент объявления задается фактический тип, и сигнатура экземпляра становится конкретизированной. Теперь экземпляр можно создать и связать с конкретной функцией. В C# 2.0 это делается проще и естественнее, чем ранее, - непосредственным присваиванием:
del1= this.max2;
При выполнении этого присваивания производятся довольно сложные действия - проверяется соответствие сигнатуры функции в правой части и экземпляра делегата, в
случае успеха создается новый экземпляр делегата, который и связывается с функцией.
Покажем, что и сам функциональный тип-делегат можно объявлять с родовыми параметрами. Вот пример такого объявления:
public delegate T FunTwoArg<T>(T a, T b);
Добавим в наш тестовый пример код, демонстрирующий работу с этим делегатом:
FunTwoArg<int> mydel;
mydel = max2;
max = mydel(17, 21);
Console.WriteLine("max= {0}", max);
Вот как выглядят результаты работы тестового примера:
Рис. 22.7. Результаты работы с универсальными делегатами
Универсальные делегаты с успехом используются при определении событий. В частности, класс EventHandler, применяемый для всех событий, не имеющих собственных аргументов, теперь дополнен универсальным аналогом, определенным следующим образом:
public void delegate EventHandler<T> (object sender, T args)
where T:EventArgs
Этот делегат может применяться и для событий с собственными аргументами, поскольку вместо параметра T может быть подставлен конкретный тип - потомок класса EventArgs, дополненный нужными аргументами.