Как правильно писать тесты 46 Цикл разработки 46 Структура проекта с тестами 51 Утверждения (Asserts) 52 Утверждения в форме ограничений 54 Категории 56

Вид материалаТесты

Содержание


Делегаты и события Делегаты
Объявление делегата
Объявление события
Подписка на событие
Уведомление подписчиков о событии
Параметры событий
Подобный материал:
1   ...   31   32   33   34   35   36   37   38   ...   47

Делегаты и события20 21



Делегаты


Делегат – это объект, хранящий ссылку на метод. Он позволяет динамически менять вызываемые при обращении к делегату методы.


Рассмотрим задачу. Пусть есть ядерный реактор, который нужно охлаждать с помощью насосов. Возможны два способа.
  1. Насосы сами мониторят температуру реактора.
  2. Есть компонент, который мониторит температуру и включает насосы, когда температура меняется.



Оба способа имеют недостатки. При первом подходе нужно знать подходящую частоту измерений. Есть риск пропустить резкое изменение температуры. При втором подходе возникает проблема отправки команд насосам разного типа из-за того, что команды у всех насосов могут быть разными. Приходится следить за всеми возможными типами насосов.




Отправка команд довольно проблематична. При добавлении нового типа насосов придется вносить изменения в критически важный код, что чревато ошибками.




Возникает первая задача: скрыть типы насосов так, чтобы отправка им сообщений на включение была одинаковой.


В этом помогут делегаты, в которые мы поместим ссылку на метод включения насоса. При обращении к делегату будет автоматически вызван нужный метод. В коллекцию ArrayList поместим не объекты насосов, а объекты делегатов.


Объявление делегата




Создание экземпляра делегата




Вызов делегата





Делегат должен иметь сигнатуру, совпадающую с сигнатурой содержащегося в нем метода.

Делегат вызывается точно так же, как вызывается метод.


В итоге реализация включения насосов становится гораздо проще. При добавлении нового типа насоса CoreTempMonitor вообще не нужно изменять.


События




В рассматриваемом примере CoreTempMonitor все еще отвечает за включение насосов. Желательно перенести ответственность за включение на сами насосы. Нужно иметь возможность сообщить насосам о том, что им нужно включаться. Для этого нам понадобятся события.

События позволяют объекту уведомить другие объекты о том, что произошло изменение его состояния. Эти заинтересованные объекты должны зарегистрировать свой интерес в появлении события у инициатора события. В нужный момент они получат сообщение о том, что произошло событие.

Участники этого процесса:

публикатор – генерирует событие при изменении своего состояния

подписчик – имеет метод, который должен быть вызван при возникновении события.


Событие может иметь от нуля до нескольких подписчиков.





События используют делегаты, чтобы вызвать методы у подписчиков. При возникновении события могут быть вызваны несколько делегатов. Однако, нельзя быть уверен в определенной последовательности вызовов. Если в одном из делегатов возникает исключение, то может потерпеть неудачу весь процесс обработки события.


Объявление события


Для объявления события нужен делегат и событие, основанное на этом делегате.





Подписка на событие


Подписчики должны предоставить метод, который должен быть вызван при возникновении события. Если экземпляр события еще не создан, то подписчик создает делегата, которому передает ссылку на свой метод. Если создан, то подписчик просто добавляет очередного делегата к событию.




Делегаты, используемые с событиями должны иметь тип возвращаемого значения void.


Уведомление подписчиков о событии


Событие в некоторый момент должно быть сгенерировано. Синтаксис для этого такой же как при обращении к делегату. Однако, нужно проверить, что у события есть подписчики. Другими словами, нужно проверить, что объект события существует.




После генерации события будут вызваны все его делегаты.


Параметры событий




Параметры событий должны наследовать класс EventArgs.

Один и тот же метод может быть вызван при возникновении разных событий. Поэтому нужно передавать в качестве первого параметра ссылку на публикатора события.

Создадим класс для параметр события:



Учитывая, что параметров у события в итоге получается два, введем события с параметрами для нашего примера:




При использовании события с параметрами нужно не забыть так же поменять и тип делегата:





Содержание 1

Процесс разработки программного обеспечения 3

Основные принципы объектно-ориентированного программирования (начало) 12

История 14

Основные принципы объектно-ориентированного программирования (продолжение) 15

Главные понятия 15

Основные принципы 15

Абстракция данных 15

Инкапсуляция 16

Наследование 16

Основные принципы объектно-ориентированного программирования (окончание) 18

Полиморфизм 18

Отношения 19

Основы .NET Framework 22

Введение 22

Обзор выполнения кода в среде CLR 26

Компиляция исходного кода в управляемые модули 26

Части управляемого модуля 28

Объединение управляемых модулей в сборку 29

Загрузка CLR при выполнении программы 31

Исполнение кода сборки 31

IL и верификация 36

Небезопасный код 36

IL и защита интеллектуальной собственности 37

NGen.exe — генератор объектного кода 38

Библиотека классов .NET Framework 38

Общая система типов (Common Type System, CTS) 40

Общеязыковая спецификация 42

Модульное тестирование (unit testing) 44

Предпосылки 44

Преимущества 44

Поощрение изменений 45

Упрощение интеграции 45

Документирование кода 45

Отделение интерфейса от реализации 45

Ограничения 46

Как правильно писать тесты 46

Цикл разработки 46

Структура проекта с тестами 51

Утверждения (Asserts) 52

Утверждения в форме ограничений 54

Категории 56

Настройка среды выполнения тестов 57

Дополнительные утверждения 59

Тесты и исключения 60

Правила тестирования 62

Юнит-тестирование 70

Пример 70

Два вида констант 98

Операторы is, as и приведение типов 101

Метод ToString() 109

Типы-значения и ссылочные типы 117

Неизменяемые (Immutable) атомарные типы-значения 122

0 в типах-значениях 132

Методы ReferenceEquals(), Equals(), статический метод Equals() и operator== 134

Циклы foreach 140

Управление ресурсами в .NET 143

Инициализаторы переменных 149

Инициализация статических полей классов с помощью статических конструкторов 155

Цепочки конструкторов 157

Применение операторов using и try/finally для освобождения ресурсов 160

О минимизации мусора 167

Упаковка и распаковка 169

Наследование классов и реализация интерфейсов 171

Отличие реализации методов интерфейса от переопределения виртуальных методов 178

Введение в паттерны проектирования 184

Что такое паттерн проектирования 186

Паттерны проектирования в схеме MVC 188

Описание паттернов проектирования 190

Каталог паттернов проектирования 192

Как решать задачи проектирования с помощью паттернов 195

Механизмы повторного использования 204

Сравнение структур времени выполнения и времени компиляции 210

Проектирование с учетом будущих изменений 212

Как выбирать паттерн проектирования 220

Как пользоваться паттерном проектирования 221

Делегаты и события 226

Делегаты 226

События 230

Параметры событий 233

Атрибуты 237

Синтаксис 237

Создание атрибута 240

Составляющие класса атрибута 242

Получение значений атрибута 244

Задание 1 245

Задание 2 246

Обобщения 251

Проблемы создания объектных образов и восстановления значений 252

Типовая безопасность и строго типизованные коллекции 253

Проблемы создания объектных образов и строго типизованные коллекции 258

Пространство имен System.Collections.Generic 259

Тип List 260

Создание обобщенных методов 263

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

Создание обобщенных структур (и классов) 267

Ключевое слово default в обобщенном программном коде 269

Создание пользовательских обобщенных коллекций 271

Установка ограничений для параметров типа с помощью where 274

Отсутствие поддержки ограничений при использовании операций 279

Создание обобщенных базовых классов 280

Создание обобщенных интерфейсов 282

Создание обобщенных делегатов 284

Несколько слов о вложенных делегатах 286

Задачи 286

Примеры реализации по шаблонам Мост+Фабрика 289

Пример 1 289

Пример 2 292

Пример 3. Контроллер в виде интерфейса, а не класса. 294

Различное поведение фабрик 298

Фабрики для создания плагинов 299

Фабрики для создания объектов по некоторому алгоритму 300

Фабрики для клонирования объектов 300

Некоторые замечания об использовании свойств и наследования 302

Замечания об использовании свойств 302

Замечания об использовании наследования. Проблема «хрупкого» базового класса. 304