.Net: События в С#
Введение
Концептуальная роль событий заключается в следующем: Если какой-то объект хочет оповестить других о смене своего состояния, он запускает событие (или сигнал). Это событие может быть отловлено любым количеством объектом. Реакцией на событие, как правило, является вызов метода в отлавливающем объекте.В языке C# события являются более развитой системой использование групповых делегатов.
При создании события его необходимо объявить:
< Модификатор доступа > event < Тип делегата > < Имя события>;
…таким образом событие имеет сигнатуру делегата. Вызов события происходит также как и вызов делегата.
Работа с событиями
Работа с событиями состоит из 3-х важных пунктов:1. Создание события.
2. Регистрация обработчика события.
3. Генерация события.
public delegate void Process(int val);
public class ExampleClass
{
private int _field;
public event Process NegativeValue; //объявление события
public void SetField(int newValue)
{
_field = newValue;
if (newValue < 0)
{
if (NegativeValue != null)
NegativeValue(newValue);
}
}
}
Рассмотрим этап регистрации получателя события. Для того чтобы отреагировать на событие, его надо ассоциировать с обработчиком события.
Обработчиком события может быть метод, совпадающий по типу с типом события (делегатом). В качестве обработчика может выступать анонимный
метод или лямбда-оператор.
class Program
{
public static void Reaction(int i)
{
Console.WriteLine("{0} is a negative value", i);
}
public static void Main()
{
var c = new ExampleClass();
c.SetField(-200); // Нет обработчиков, нет и реакции.
//Если бы при генерации события отсутствовала проверка на null, то предыдущая строка вызвала бы исключительную ситуацию
c.NegativeValue += Reaction; // Назначаем обработчик. Теперь будет вывод "-10 is a negative value"
c.SetField(-10); // Назначаем еще один обработчик
c.NegativeValue += i => Console.WriteLine(i); // Используем лямбда-оператор.
c.SetField(-10); //Вывод: "-10 is a negative value" и "-10"
c.NegativeValue -= Reaction; // Удаляем первый обработчик
}
}
В реальности, событие это набор методов: первый начинается с приставки add_, а второй — с приставки remove_, что становится прекрасно видно с помощью дизассемблера IL.
Определение события в одной строке является фактически сокращенной версией записи методов, работающих с обработчиками.
Методы добавления и удаления делегата из события генерируются автоматически, однако программист может их переопределить, используя следующую запись:
event <имя делегата> <имя события>
{
add { }
remove { }
};
Что в принципе удобно, если необходимо осуществить более сложные операции, чем простое добавление и удаление обработчика.
Т.к. события создаются на основе делегатов, которые могут указывать не только на один метод, то соотвтественно и события могут «возбуждать» сразу несколько обработчиков. Многоадресные события позволяют множеству объектов «реагировать» на извещение о событии.
Стандартные делегаты
.NET предлагает средства для упрощения работы с событиями. Имеются следующие стандартные делегаты:public delegate void EventHandler(object sender, EventArgs e);
public delegate void EventHandler(object sender,TEventArgs e)
where TEventArgs : EventArgs;
object sender – объект, который генерирует событие.
EventArgs e – объект, содержащий аргументы( параметры ) события
Внесём изменения в код класса ExampleClass для работы с вышеперечисленными делегатами.
public class MyEventArg : EventArgs
{
public int NewValue { get; private set; }
public MyEventArg(int newValue)
{
NewValue = newValue;
}
}
public class ExampleClass
{
private int _field;
public event EventHandler NegativeValue;
public void SetField(int newValue)
{
_field = newValue;
if (newValue < 0)
OnNegativeValueSet(newValue);
}
protected virtual void OnNegativeValueSet(int value)
{
if (NegativeValue != null)
NegativeValue(this, new MyEventArg(value));
}
}
Методы расширения и события
Класс EventHelper содержит несколько методов расширения, упрощающих генерацию событий.
public event EventHandler<EventArgs> FrameSent;
public class EventArgs : EventArgs
{
public T EventInfo { get; private set; }
public EventArgs(T eventInfo)
{
EventInfo = eventInfo;
}
}
public static class EventHelper
{
public static void Raise(this EventHandler<EventArgs> eventHandler,
object sender, T args)
{
if (eventHandler != null)
eventHandler(sender, new EventArgs(args));
}
public static void Raise(this EventHandler<EventArgs> eventHandler, T args)
{
if (eventHandler != null)
eventHandler(null, new EventArgs(args));
}
public static void Raise(this EventHandler eventHandler,object sender, EventArgs args)
{
if (eventHandler != null)
eventHandler(sender, args);
}
Пример использования метода расширения из класса EventHelper:
FrameSent.Raise(this, frame);
Это позволяет намного упростить весь процесс работы с событиями.
Пример использования метода расширения из класса EventHelper:
FrameSent.Raise(this, frame);
Это позволяет намного упростить весь процесс работы с событиями.
0 комментариев