Volatile 13 страница. b.Click += new EventHandler( );
b.Click += new EventHandler(…); где делегат добавляется к списку вызовов события Click, и в b.Click –= new EventHandler(…); где делегат удаляется из списка вызовов события Click. При компиляции события, подобного полю, компилятор автоматически создает хранилище для хранения делегата и создает методы доступа для события, добавляющие или удаляющие обработчики событий поля делегата. Чтобы быть потокобезопасными, операции добавления и удаления выполняются при блокировке (§8.12) содержащего объекта для события экземпляра или объекта типа (§7.5.10.6) для статического события. Так, объявление события экземпляра вида: class X можно скомпилировать в нечто, эквивалентное: class X public event D Ev { remove { Внутри класса X ссылки на Ev компилируются в ссылки на скрытое поле __Ev. Имя "__Ev" произвольное; скрытое поле могло бы иметь любое имя или вообще его не иметь. Аналогично объявление статического события вида: class X можно скомпилировать в нечто, эквивалентное: class X public static event D Ev { remove { 10.8.2 Методы доступа к событиям В объявлениях событий обычно опускаются объявления_доступа_к_событиям, как в вышеприведенном примере Button. В число причин для этого входит случай, когда затраты на хранение одного поля на каждое событие не являются приемлемыми. В таких случаях класс может включать объявления_методов_доступа_к_событиям и использовать частный механизм для хранения списка обработчиков событий. Объявления_методов_доступа_к_событиям события указывают исполняемые операторы, связанные с добавлением и удалением обработчиков событий. Объявления методов доступа состоят из объявления_метода_доступа_add и объявления_метода_доступа_remove. Каждое объявление метода доступа состоит из лексемы add или remove, за которой следует блок. В блоке, связанном с объявлением_метода_доступа_add, указываются операторы, выполняемые при добавлении обработчика событий, а в блоке, связанном с объявлением_метода_доступа_remove, указываются операторы, выполняемые при удалении обработчика событий. Каждое объявление_метода_доступа_add и объявление_метода_доступа_remove соответствует методу с одним параметром значения типа события и типом возвращаемого значения void. Неявный параметр метода доступа к событию называется value. Когда событие используется в назначении события, используется соответствующий метод доступа к событию. В частности, если оператором присваивания является +=, используется метод доступа add, а если оператор присваивания -=, используется метод доступа remove. В любом случае правый операнд оператора присваивания используется в качестве аргумента метода доступа к событию. Блок объявления_метода_доступа_add или объявления_метода_доступа_remove должен соответствовать правилам для методов void, описанным в §10.6.10. В частности, операторам return в таком блоке запрещено указывать выражение. Поскольку в методе доступа к событию неявно имеется параметр с именем value, объявление в методе доступа к событию локальной переменной или константы с таким именем является ошибкой времени компиляции. В примере class Control: Component // Вернуть обработчик событий, связанный с ключом // Добавить обработчик событий, связанный с ключом // Удалить обработчик событий, связанный с ключом // Событие MouseDown // Событие MouseUp // Вызвать событие MouseUp класс Control реализует механизм внутреннего хранилища для событий. Метод AddEventHandler связывает значение делегата с ключом, метод GetEventHandler возвращает делегат, в данный момент связанный с ключом, а метод RemoveEventHandler удаляет делегат в качестве обработчика событий для указанного события. Предположительно, лежащий в основе механизм хранилища разработан так, что отсутствуют затраты на связывание значения делегата null с ключом, и таким образом необрабатываемые события не расходуют емкость хранилища. 10.8.3 Статические события и события экземпляров Если в объявление события включен модификатор static, событие называют статическим событием. Если нет модификатора static, событие называют событием экземпляра. Статическое событие не связано с конкретным экземпляром, и обращение к this в методах доступа статического события является ошибкой времени компиляции. Событие экземпляра связано с данным экземпляром класса, и к этому экземпляру можно обращаться как к this (§7.5.7) в методах доступа этого события. Когда к событию обращаются через доступ_к_члену (§7.5.4) вида E.M, если M является статическим событием, E должно означать тип, содержащий M, а если M является событием экземпляра, E должно означать экземпляр типа, содержащего M. Различия между статическими членами и членами экземпляров обсуждаются далее в §10.3.7. 10.8.4 Виртуальные, запечатанные, переопределяющие и абстрактные методы доступа Объявление события как virtual указывает, что методы доступа этого события являются виртуальными. Модификатор virtual применяется к обоим методам доступа события. Объявление события как abstract указывает, что методы доступа события являются виртуальными, но не предоставляет фактическую реализацию методов доступа. Вместо этого требуются не абстрактные производные классы для предоставления их собственной реализации для методов доступа посредством переопределения события. Поскольку объявление абстрактного события не предоставляет фактическую реализацию, оно не может предоставить разделенные скобками объявления_методов_доступа_к_событиям.
|