Реализация групповых вызовов
Реализация групповых вызовов
Напомним, что делегаты .NET наделены возможностью группового вызова. Другими словами, объект делегата может поддерживать не один метод, а целый список доступных для вызова методов. Когда требуется добавить в объект делегата несколько методов, используется перегруженная операция +=, а не прямое присваивание. Чтобы разрешить групповой вызов для типа Car, можно обновить методы OnAboutToBlow() и OnExploded() так, как показано ниже.
public class Car {
// Добавление элемента в список вызовов.
public void OnAboutToBlow(AboutToBlow clientMethod) {almostDeadList += clientMethod;}
public void OnExploded(Exploded clientMethod) {explodedList += clientMethod;}
…
}
Теперь вызывающая сторона может зарегистрировать несколько целевых объектов.
class Program {
static void Main(string[] args) {
Car c1 = new Car("SlugBug", 100, 10);
// Регистрация множества обработчиков событий.
c1.OnAboutToBlow(new Car.AboutToBlow(CarAboutToBlow));
c1.OnAboutToBlow(new Car.AboutToBlow(CarlsAlmostDoomed));
c1.OnExploded(new Car.Exploded(CarExploded));
…
}
// Car будет вызывать эти методы.
public static void CarAboutToBlow(string msg) {Console.WriteLine (msg);}
public static void CarIsAlmostDoomed(string msg) {Console.WriteLine("Важное сообщение от Car: {0}", msg);}
public static void CarExploded(string msg) {Console.WriteLine(msg);}
}
В программном воде CIL операция += преобразуется в вызов статического метода Delegate.Combine() (можно было бы вызвать Delegate.Combine() непосредственно, но операция += предлагает более простую альтернативу). Взгляните, например, на CIL-представление метода OnAboutToBlow().
.method public hidebysig instance void OnAboutToBlow (class CarDelegate.Car/AboutToBlow clientMethod) cil managed {
.maxstack 8
ldarg.0
dup
ldfld class CarDelegate.Car/AboutToBlow CarDelegate.Car::almostDeadList
ldarg.1
call class [mscorlib]System.Delegate [mscorlib]System.Delegate::Combine(class [mscorlib]System.Delegate, class [mscorlib]System.Delegate)
castclass CarDelegate.Car/AboutToBlow
stfld class СarDelegate.Car/AboutToBlow CarDelegate.Car::almostDeadList
ret
}
Класс Delegate определяет также статический метод Remove(), который позволит вызывающей стороне динамически удалять элементы из списка вызовов. Легко догадаться, что в C# разработчики могут для этого использовать перегруженную операцию -=. Чтобы предоставить вызывающей стороне возможность не привязываться к обозначениям AboutToBlow и Exploded, можно добавить в тип Car следующие вспомогательные методы (обратите внимание на операцию -=).
public class Car {
// Удаление элемента из списка вызовов.
public void RemoveAboutToBlow(AboutToBlow clientMethod) {almostDeadList -= clientMethod;}
public void RemoveExploded(Exploded clientMethod) {explodedList -= clientMethod;}
...
}
Здесь синтаксис -= тоже выступает в качестве простого сокращения для вызова статического метода Delegate.Remove(), что доказывается следующим программным кодом CIL для члена RemoveAboutToBlow() типа Car.
.method public hidebysig instance void RemoveAboutToBlow(class CarDelegate.Car/AboutToBlow clientMethod) cil managed {
.maxstack 8
ldarg.0
dup
ldfld class CarDelegate.Car/AboutToBlow CarDelegate.Car::almostDeadList
ldarg.1
call class [mscorlib]System.Delegate [mscorlib]System.Delegate::Remove(class [mscorlib]System.Delegate, class [mscorlib]System.Delegate)
castclass CarDelegate.Car/AboutToBlow
stfld class CarDelegate.Car/AboutToBlow CarDelegate.Car::almostDeadList
ret
}
Если вызывающая сторона пожелает удалить элемент из списка вызовов делегата, мы должны предоставить тот же объект делегата, который был ранее добавлен. Поэтому мы можем прекратить выдачу сообщения Exploded, обновив Main() так, как показано ниже.
static void Main(string[] args) {
Car cl = new Car("SlugBug", 100, 10);
// Сохранение объекта Car.Exploded делегата.
Car.Exploded d = new Car.Exploded(CarExploded);
cl.OnExploded(d);
…
// Удаление метода CarExploded из списка вызовов.
cl.RemoveExploded(d);
…
}
Вывод нашего приложения CarDelegate показан на рис. 8.5.

Рис. 8.5. Приложение CarDelegate за работой
Исходный код. Проект CarDelegate размещен в подкаталоге, соответствующем главе 8.
Более 800 000 книг и аудиокниг! 📚
Получи 2 месяца Литрес Подписки в подарок и наслаждайся неограниченным чтением
ПОЛУЧИТЬ ПОДАРОКЧитайте также
Производительность системных вызовов
Производительность системных вызовов Системные вызовы в операционной системе Linux работают быстрее, чем во многих других операционных системах. Это отчасти связано с невероятно малым временем переключения контекста. Переход в режим ядра и выход из него являются хорошо
Реализация системных вызовов
Реализация системных вызовов Реализация системного вызова в ОС Linux не связана с поведением обработчика системных вызовов. Добавление нового системного вызова в операционной системе Linux является сравнительно простым делом. Тяжелая работа связана с разработкой и
Кэширование ресурсоемких вызовов
Кэширование ресурсоемких вызовов Как показывает практика, лучше всего будет использовать переменные максимально близко к области их объявления и избегать использования глобальных переменных любой ценой. Глобальная область видимости обычно содержит десятки, если не
Кэшируем цепочки вызовов
Кэшируем цепочки вызовов Распознавание (разрешение) ссылки на объект или метод выполняется каждый раз, когда происходит обращение к этому объекту или методу. Переменные разрешаются всегда в обратном порядке: от более частной области видимости к более общей. Поэтому,
9.2.1. Ограничения системных вызовов
9.2.1. Ограничения системных вызовов Режим ядра защищен от влияния режима пользователя. Одна из таких защит состоит в том, что тип данных, передаваемых между режимами ядра и пользователя, ограничен, легко верифицируется и следует строгим соглашениям.• Длина каждого
9.2.3. Использование системных вызовов
9.2.3. Использование системных вызовов Интерфейс, с которым вам, как программисту, возможно, доведется работать, представляет собой набор оболочек библиотеки С для системных вызовов. В оставшейся части этой книги под системным вызовом будет подразумеваться функция
Просмотр стека вызовов
Просмотр стека вызовов В отладчике можно вывести окно Call Stack со списком всех активных процедур и функций сценария. Для этого нужно выполнить команду View|Call Stack. Например, если вызвать это окно, находясь внутри функции MyFunc() в сценарии ForDebug.js, то в списке мы увидим название
В.1. Трассировка системных вызовов
В.1. Трассировка системных вызовов Многие версии Unix предоставляют возможность трассировки (отслеживания) системных вызовов. Зачастую это может оказаться полезным методом отладки.Работая на этом уровне, необходимо различать системный вызов и функцию. Системный вызов
16.6. Семантика вызовов
16.6. Семантика вызовов В листинге 15.24 мы привели пример клиента интерфейса дверей, повторно отсылавшего запрос на сервер при прерывании вызова door_call перехватываемым сигналом. Затем мы показали, что при этом процедура сервера вызывается дважды, а не однократно. Потом мы
2.2.2. Ошибки системных вызовов
2.2.2. Ошибки системных вызовов Большинство из нас училось писать программы, которые выполняются по четко намеченному алгоритму. Мы разделяли программу на задачи и подзадачи, и каждая функция решала свою задачу, вызывая другие функции для решения соответствующих подзадач.
Использование групповых политик
Использование групповых политик Ветвь реестра HKEY_CURRENT_USERSoftwareMicrosoftWindowsCurrentVersionPoliciesExplorerRun определяет программы, которые будут автоматически запускаться при входе пользователя в систему. Она содержит параметры строкового типа, имена которых формируются в такой
Оптимизация вызовов
Оптимизация вызовов На уровнях 2 и 3 неизбежно использование явных вызовов процедуры подобных my_polygon.set_size (5) для изменения значения атрибута. Существует опасение, что использование такого стиля на уровне 4 негативно скажется на производительности. Тем не менее компилятор
Цепочка вызовов
Цепочка вызовов Обсуждая механизм обработки исключений, полезно иметь ясную картину последовательности вызовов, приведших в итоге к исключению. Это понятие уже появлялось при рассмотрении механизма языка Ada. Рис. 12.1. Цепочка вызововПусть r0 будет корневой процедурой
4.2.4. Создание групповых списков рассылки
4.2.4. Создание групповых списков рассылки Используя групповые списки рассылки, вы сможете одним щелчком мыши отправить сообщения сразу всем адресатам, входящим в одну конкретную группу. Для создания группы необходимо выполнь следующее:1. Щелкнуть по кнопке «+»,