Рассмотрим два способа объявления событий.
Либо вы объявляете событие, используя явный метод add
/remove
, либо вы объявляете событие без таких методов.
Другими словами, вы объявляете событие следующим образом:
public event EventHandlerType EventName
{
add
{
// some code here
}
remove
{
// some code here
}
}
или вы объявляете это так:
public event EventHandlerType EventName;
Дело в том, что в чем-то они одинаковы, а в чем-то совершенно разные.
С точки зрения внешнего кода, то есть... кода вне класса, публикующего событие, это одно и то же. Чтобы подписаться на событие, вы вызываете метод. Чтобы отказаться от подписки, вы вызываете другой метод.
Разница в том, что во втором примере кода выше эти методы будут предоставлены компилятором для вас, однако это все равно будет так. Чтобы подписаться на событие, вы вызываете метод.
Синтаксис для этого в C#, однако, одинаков, вы делаете либо:
objectInstance.EventName += ...;
or:
objectInstance.EventName -= ...;
Таким образом, с «внешней точки зрения» эти два пути ничем не отличаются.
Однако внутри класса есть разница.
Если вы пытаетесь получить доступ к EventName
идентификатору внутри класса, вы на самом деле ссылаетесь на field
, который поддерживает свойство, но только если вы используете синтаксис, который явно не объявляет add
/remove
метод.
Типичный шаблон выглядит следующим образом:
public event EventHandlerType EventName;
protected void OnEventName()
{
var evt = EventName;
if (evt != null)
evt(this, EventArgs.Empty);
}
В этом случае, когда вы имеете в виду EventName
, вы на самом деле имеете в виду поле, содержащее делегата типа EventHandlerType
.
Однако, если вы явно объявили методы add
/remove
, ссылка на идентификатор EventName
внутри класса будет такой же, как и вне класса, поскольку компилятор не может гарантировать, что он знает поле или любой другой механизм, в котором вы сохранить подписку.
person
Lasse V. Karlsen
schedule
28.04.2012