Работал ли с событиями (Events) в C#?

«Работал ли с событиями (Events) в C#?» — вопрос из категории C# Core, который задают на 25% собеседований C# Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Да, постоянно работаю. События (Events) в C# — это реализация шаблона Наблюдатель (Observer), позволяющая объекту (издателю) уведомлять другие объекты (подписчиков) о возникновении какого-либо действия.

Базовый пример объявления и использования:

// 1. Объявление делегата для события (стандартный шаблон EventHandler<T>)
public class OrderEventArgs : EventArgs
{
    public string OrderId { get; set; }
}

// 2. Класс-издатель (Publisher)
public class OrderService
{
    // Объявление события с использованием обобщенного делегата EventHandler<T>
    public event EventHandler<OrderEventArgs> OrderPlaced;

    public void PlaceOrder(string orderId)
    {
        // Логика размещения заказа...
        Console.WriteLine($"Заказ {orderId} создан.");

        // 3. Вызов события (уведомление подписчиков)
        OnOrderPlaced(new OrderEventArgs { OrderId = orderId });
    }

    // Виртуальный метод для безопасного вызова события
    protected virtual void OnOrderPlaced(OrderEventArgs e)
    {
        OrderPlaced?.Invoke(this, e); // Проверка на null перед вызовом
    }
}

// 4. Класс-подписчик (Subscriber)
public class NotificationService
{
    public void Subscribe(OrderService orderService)
    {
        // Подписка на событие
        orderService.OrderPlaced += HandleOrderPlaced;
    }

    // Обработчик события
    private void HandleOrderPlaced(object sender, OrderEventArgs e)
    {
        Console.WriteLine($"Уведомление: Заказ {e.OrderId} готов к обработке.");
    }
}

// Использование
var orderService = new OrderService();
var notifier = new NotificationService();
notifier.Subscribe(orderService);
orderService.PlaceOrder("ORD-12345");

Зачем это нужно: События обеспечивают слабую связность (loose coupling). Класс-издатель не знает о конкретных подписчиках, а лишь предоставляет точку для подписки. Это фундаментальный механизм для реализации реактивного программирования, UI-событий (WinForms, WPF) и межмодульного взаимодействия.