- •Сборки (assembly) в среде .Net. Проблема версионности сборок и ее решение.
- •Номер версии в .Net
- •Сведения о версии
- •Номер версии сборки
- •Информационная версия сборки
- •Общая система типов данных в среде .Net. Размерные и ссылочные типы данных. Типы, переменные и значения
- •Пользовательские типы
- •Система общих типов cts
- •Ссылочные типы
- •Типы литеральных значений
- •Неявные типы, анонимные типы и типы, допускающие значение null
- •Упаковка и распаковка размерных типов данных в среде .Net.
- •Производительность
- •Упаковка–преобразование
- •Распаковка-преобразование
- •Ссылочные типы данных. Объектная модель в среде .Net и языке c#.
- •Модели ручной и автоматической утилизации динамической памяти, их сравнительная характеристика. Модель с ручным освобождением памяти
- •Модель с автоматической «сборкой мусора»
- •Модель автоматической утилизации динамической памяти, основанная на сборке мусора. Проблема недетерминизма.
- •Модель автоматической утилизации динамической памяти, основанная на аппаратной поддержке (тегированной памяти).
- •Сборка мусора в среде .Net. Построение графа достижимых объектов.
- •Сборка мусора в среде .Net. Механизм поколений объектов.
- •Модель детерминированного освобождения ресурсов в среде .Net. Интерфейс iDisposable и его совместное использование с завершителем (методом Finalize).
- •«Мягкие ссылки» и кэширование данных в среде .Net.
- •Краткие и длинные слабые ссылки
- •Краткая ссылка
- •Длинная ссылка
- •Правила использования слабых ссылок
- •Динамические массивы в среде .Net и языке c#.
- •Приведение типов в массивах
- •Все массивы неявно реализуют /Enumerable, /Collection и iList
- •Передача и возврат массивов
- •Создание массивов с ненулевой нижней границей
- •Производительность доступа к массиву
- •Небезопасный доступ к массивам и массивы фиксированного размера
- •Делегаты в среде .Net и механизм их работы. Знакомство с делегатами
- •Использование делегатов для обратного вызова статических методов
- •Использование делегатов для обратного вызова экземплярных методов
- •Правда о делегатах
- •Использование делегатов для обратного вызова множественных методов (цепочки делегатов)
- •Поддержка цепочек делегатов в с#
- •Расширенное управление цепочкой делегатов
- •Упрощение синтаксиса работы с делегатами в с#
- •Упрощенный синтаксис № 1: не нужно создавать объект-делегат
- •Упрощенный синтаксис № 2: не нужно определять метод обратного вызова
- •Упрощенный синтаксис № 3: не нужно определять параметры метода обратного вызова
- •Упрощенный синтаксис № 4: не нужно вручную создавать обертку локальных переменных класса для передачи их в метод обратного вызова
- •Делегаты и отражение
- •События в среде .Net; реализация событий посредством делегатов. События
- •Этап 1: определение типа, который будет хранить всю дополнительную информацию, передаваемую получателям уведомления о событии
- •Этап 2: определение члена-события
- •Этап 3: определение метода, ответственного за уведомление зарегистрированных объектов о событии
- •Этап 4: определение метода, транслирующего входную информацию в желаемое событие
- •Как реализуются события
- •Создание типа, отслеживающего событие
- •События и безопасность потоков
- •Явное управление регистрацией событий
- •Конструирование типа с множеством событий
- •Исключительные ситуации и реакция на них в среде .Net. Достоинства
- •Механика обработки исключений
- •Блок try
- •Блок catch
- •Блок finally
- •Генерация исключений
- •Определение собственных классов исключений
- •Исключения в платформе .Net Framework
- •Исключения и традиционные методы обработки ошибок
- •Управление исключениями средой выполнения
- •Фильтрация исключений среды выполнения
- •21 Средства многопоточного программирования в среде .Net. Автономные потоки. Пул потоков.
- •Создание и использование потоков
- •Запуск и остановка потоков
- •Методы управления потоками
- •Безопасные точки
- •Свойства потока
- •Потоки Windows в clr
- •К вопросу об эффективном использовании потоков
- •Пул потоков в clr
- •Ограничение числа потоков в пуле
- •22. Асинхронные операции в среде .Net. Асинхронный вызов делегатов.
- •23. Синхронизация программных потоков в среде .Net. Блокировки.
- •Двойная блокировка
- •Класс ReaderWriterLock
- •Использование объектов ядра Windows в управляемом коде
- •Вызов метода при освобождении одного объекта ядра
- •24. Синхронизация программных потоков в среде .Net. Атомарные (Interlocked-операции). Семейство lnterlocked-методов
- •25. Прерывание программных потоков в среде .Net. Особенности исключительной ситуации класса ThreadAbortException.
- •26. Мониторы в среде .Net. Ожидание выполнения условий с помощью методов Wait и Pulse. Класс Monitor и блоки синхронизации
- •«Отличная» идея
- •Реализация «отличной» идеи
- •Использование класса Monitor для управления блоком синхронизации
- •Способ синхронизации, предлагаемый Microsoft
- •Упрощение кода c# при помощи оператора lock
- •Способ синхронизации статических членов, предлагаемый Microsoft
- •Почему же «отличная» идея оказалась такой неудачной
- •Целостность памяти, временный доступ к памяти и volatile-поля
- •Временная запись и чтение
- •Поддержка volatile-полей в с#
- •27. Асинхронный вызов делегатов.
- •Общие типы (Generics)
- •Инфраструктура обобщений
- •Открытые и закрытые типы
- •Обобщенные типы и наследование
- •Проблемы с идентификацией и тождеством обобщенных типов
- •«Распухание» кода
- •Обобщенные интерфейсы
- •Обобщенные делегаты
- •Обобщенные методы
- •Логический вывод обобщенных методов и типов
- •Обобщения и другие члены
- •Верификация и ограничения
- •Основные ограничения
- •Дополнительные ограничения
- •Ограничения конструктора
- •Другие вопросы верификации
- •Приведение переменной обобщенного типа
- •Присвоение переменной обобщенного типа значения по умолчанию
- •Сравнение переменной обобщенного типа с null
- •Сравнение двух переменных обобщенного типа
- •Использование переменных обобщенного типа в качестве операндов
- •Преимущества использования общих типов
- •29. Итераторы в среде .Net. Создание и использование итераторов.
- •Общие сведения о итераторах
Создание типа, отслеживающего событие
Ну, самое трудное позади. В этом разделе я покажу, как определить тип, использующий событие, поддерживаемое другим типом. Начнем с изучения исходного текста типа Fax.
internal sealed class Fax
{
// Передаем конструктору объект MailManager.
public Fax(MailManager mm)
{
// Создаем экземпляр делегата EventHandler<NewMailEventArgs>,
// ссылающийся на метод обратного вызова FaxMsg.
// Регистрируем обратный вызов для события NewMail объекта MailManager.
mm.NewMail += FaxMsg;
}
// MailManager вызывает этот метод для уведомления
// объекта Fax о прибытии нового почтового сообщения.
private void FaxMsg(Object sender, NewMailEventArgs e)
{
// 'sender' можно использовать для взаимодействия с объектом MailManager,
// если нужно вернуть ему какую-то информацию.
// 'е' указывает дополнительную информацию о событии,
// которую пожелает предоставить MailManager.
// Обычно расположенный здесь код отправляет сообщение по факсу.
// В тестовом варианте программы этот метод
// выводит информацию в консоль.
Console.WriteLine("Faxing mail message:");
Console.WriteLine("From={0}, To={1}, Subject={2}", e.From, e.To, e.Subject);
}
// Этот метод может выполняться для отмены регистрации объекта Fax
// на получение уведомлений о событии NewMail.
public void Unregister(MailManager mm)
{
// Отменить регистрацию на уведомление о событии NewMail
// объекта MailManager. ,
mm.NewMail -= FaxMsg;
}
}
При инициализации почтовое приложение сначала создает объект MailManager и сохраняет ссылку на него в переменной. Затем оно создает объект Fax, передавая ссылку на MailManager как параметр. После создания делегата, объект Faxрегистрируется при помощи оператора «+=» языкаC# для уведомления о событииNewMailобъектаMailManager.
mm.NewMail += FaxMsg;
Обладая встроенной поддержкой событий, компилятор C# транслирует оператор += в код, регистрирующий объект для получения уведомлений о событии:
mm.add_NewMail(new EventHandler<NewMailEventArgs>(this.FaxMsg));
Компилятор C# создает код, конструирующий делегат EventHandler<NewMailEventArgs>, инкапсулирующий метод NewMail класса Fax. Затем компиляторC# вызывает метод addNewMail объекта MailManager, передавая ему новый делегат.
Даже используя язык, не поддерживающий события напрямую, можно зарегистрировать делегат для уведомления о событии, явно вызвав метод-аксессор add. Результат идентичен, только исходный текст при этом получается не столь изящным. Именно метод add, регистрирующий делегат для уведомления о событии, добавляет делегат в связный список делегатов данного события.
Когда срабатывает событие объекта MailManager, вызывается метод FaxMsg объекта Fax. Этому методу передается ссылка на объект MailManager в качестве первого параметра, или sender. Чаще всего этот параметр игнорируется, но он может и использоваться, если в ответ на уведомление о событии объект Fax пожелает получить доступ к полям или методам объекта MailManager. Второй параметр — это ссылка на объект NewMailEventArgs. Этот объект содержит всю дополнительную информацию, которая, по мнению NewMailEventArgs, может быть полезной для получателей события.
При помощи объекта NewMailEventArgs метод FaxMsg может без труда получить доступ к сведениям об отправителе и получателе сообщения, его теме и собственно тексту. Реальный объект Fax отправлял бы эти сведения адресату, а в этом примере они просто выводятся на консоль.
Когда объекту больше не нужны уведомления о событиях, он должен отменить свою регистрацию. Например, объект Fax отменит свою регистрацию для уведомления о событии NewMail, если пользователю больше не нужно пересылать сообщения электронной почты по факсу. Пока объект зарегистрирован для уведомления о событии другого объекта, он не может стать добычей сборщика мусора. Если в вашем типе реализован метод Dispose объекта /Disposable, уничтожение объекта должно вызвать отмену его регистрации для уведомления обо всех событиях (об объекте IDisposable см. также главу 20).
Код, иллюстрирующий отмену регистрации, показан в исходном тексте метода Unregister объекта Fax. Код этого метода фактически идентичен конструктору типа Fax. Единственное отличие в том, что здесь вместо «+=» использован оператор «-=». Обнаружив код, отменяющий регистрацию делегата при помощи оператора «-=», компилятор С# генерирует вызов метода remove этого события-.
mm.remove_NewMail(new EventHandler<NewMailEventArgs>(FaxMsg));
Как и в случае оператора «+=», даже при использовании языка, не поддерживающего события напрямую, можно отменить регистрацию делегата, явно вызывая метод-аксессор remove, который отменяет регистрацию делегата путем сканирования связного списка в поисках делегата-оболочки метода, соответствующего переданному методу обратного вызова. Если обнаружено совпадение, делегат удаляется из связного списка делегатов события. Если нет, ошибка не возникает, и список делегатов события остается неизменным.
Кстати, С# требует, чтобы для добавления и удаления делегатов из связного списка в ваших программах использовались операторы += и -=. Если попытаться обратиться к методам add или remove напрямую, компилятор С# сгенерирует сообщение об ошибке:
«CS0571: cannot explicitly call operator or accessor* («CS0571: оператор или аксессор нельзя вызывать явно»).