C#: События (events)
Date and time: June 2, 2015, 10:10 p.m. | Category: Программирование, C#
В отличии от многих других языков программирования, C# "из коробки" предоставляет возможность реализации событийного управления. Данный подход позволяет значительно упростить логику программы и реализован очень просто и элегантно.
Рассмотрим небольшой пример создания события на примере абстракции почтового ящика. Опишем простой класс с единственным методом - добавлением письма. Допустим, что нам требуется выполнять какое-либо действие при каждом добавлении письма (возможно какие-либо вычисление, а возможно - оповещение других объектов). Следующий код демонстрирует как это реализовать. При добавлении письма, выводится сообщение: "Получено письмо!"
using System;
namespace App
{
// Описываем делегат (читай - прототип) будущего события
public delegate void LetterReceived(object sender, EventArgs e);
public class Mailbox
{
// Создаём объект события внутри класса, чтобы к нему можно было подписаться
public event LetterReceived OnLetterReceived;
public void AddLetter(string letter)
{
// Проверяем, есть ли подписчики на событие
if (OnLetterReceived != null)
{
// Вызываем событие. Первый аргумент - инициатор события,
// второй - дополнительные аргументы события.
OnLetterReceived(this, new EventArgs());
}
}
}
class Program
{
static void Main(string[] args)
{
var mailbox = new Mailbox();
// Подписывается на событие
mailbox.OnLetterReceived += mailbox_OnLetterReceived;
mailbox.AddLetter("Письмо");
Console.Read();
}
// Реализуем обработчик события
static void mailbox_OnLetterReceived(object sender, EventArgs e)
{
Console.WriteLine("Получено письмо!");
}
}
}
Как видно, всё очень просто и этого достаточно для начала работы. Но со временем может потребоваться добавить свои аргументы событию. В классическом виде это реализуется путём наследования от класса EventArgs с добавлением необходимых полей. Например, рассмотрим тот же код, но уже передающий текст письма в аргументе события.
using System;
namespace App
{
// Описываем свой класс аргументов событий, определяя поле для письма
public class MailEventArgs : EventArgs
{
public string Letter { get; set; }
}
// Заменяем тип второго параметра делегата на наш класс
public delegate void LetterReceived(object sender, MailEventArgs e);
public class Mailbox
{
public event LetterReceived OnLetterReceived;
public void AddLetter(string letter)
{
if (OnLetterReceived != null)
{
// Создаём объект аргумента события и помещаем в него текст письма
var e = new MailEventArgs { Letter = letter };
OnLetterReceived(this, e);
}
}
}
class Program
{
static void Main(string[] args)
{
var mailbox = new Mailbox();
mailbox.OnLetterReceived += mailbox_OnLetterReceived;
mailbox.AddLetter("Письмо");
Console.Read();
}
static void mailbox_OnLetterReceived(object sender, MailEventArgs e)
{
// Добавляем к выводу сообщения текст полученного письма
Console.WriteLine(String.Format("Получено письмо!\nТекст: {0}", e.Letter));
}
}
}
Таким образом, события очень удобны. По сути, они могут заменить шаблон проектирования Наблюдатель (Observer), но между данными подходами всё же есть некоторые отличия. Наблюдатель предполагает передачу в качестве подписчика объект, а событие предполагает обработчик в виде метода. Так или иначе, обоими способами можно добиться одинаковых результатов.
comments powered by Disqus