![]() КАТЕГОРИИ:
АстрономияБиологияГеографияДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРиторикаСоциологияСпортСтроительствоТехнологияФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника
|
Этап 2: определение члена-событияВ C# член-событие объявляется ключевым словом event. Каждому члену-событию определяется: 1. область действия 2. тип делегата, указывающий на прототип вызываемого метода (методов) 3. имя Вот как выглядит член-событие нашего класса NewMail:
internal class MailManager { // Этап 2: определение члена-события public event EventHandler<NewMailEventArgs> NewMail; }
NewMail — имя события. EventHandler<NewMailEventArgs> — тип члена-события.
Получатели уведомления о событии должны предоставлять метод обратного вызова, прототип которого совпадает с типом-делегатом EventHandler<NewMailEventArgs>.
Поскольку обобщенный делегат System.EventHandler определен так: public delegate void EventHandler<TEventArgs> (Object sender, TEventArgs e) where TEventArgs : EventArgs;
метод должен выглядеть так: void MethodName(Object sender, NewMailEventArgs e);
Примечание: Многих удивляет, почему механизм событий требует, чтобы параметр sender был типа Object. Вообще-то, поскольку MailManager — единственный тип, реализующий события с объектом NewMailEventArgs, было бы разумнее использовать следующий прототип метода обратного вызова: void MethodName(MailManager sender, NewMailEventArgs e); Причина необходимости того, чтобы параметр sender был типа Object, — в наследовании. Что произойдет, если MailManager задействовать в качестве базового класса для создания класса SmtpMailManager? В методе обратного вызова придется в прототипе задать параметр sender как SmtpMailManager, а не MailManager, но этого делать нельзя, так как SmtpMailManager просто унаследовал событие NewMail. Поэтому код, ожидающий от SmtpMailManager информацию о событии, все равно будет вынужден приводить аргумент sender к типу SmtpMailManager. Иначе говоря, приведение все равно необходимо, поэтому проще всего сделать так, чтобы sender был типа Object. Еще одна причина того, что sender относят к типу Object — простая гибкость. Это позволяет использовать делегат нескольким типам, которые поддерживают событие, передающее объект NewMailEventArgs. В частности, класс PopMailManager мог бы использовать делегат, даже если бы не наследовал классу MailManager. Механизм событий требует, чтобы в имени делегата и методе обратного вызова производный от EventArgs параметр назывался е. Единственная причина — обеспечить дополнительное однообразие, облегчая и упрощая для разработчиков изучение и реализацию событий. Механизм событий требует, чтобы все обработчики возвращали void. Это обязательно, потому что при возникновении события могут вызываться несколько методов обратного вызова и невозможно получить у них всех возвращаемое значение. Тип void просто запрещает методам возвращать какое бы то ни было значение. К сожалению, в библиотеке FCL есть обработчики событий, в частности ResolveEventHandler, в которых Microsoft не следует собственным правилам и возвращает объект типа Assembly.
|