Какие стандартные события в C# ты знаешь?

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

Ответ

В C# события — это реализация шаблона наблюдатель (Observer), построенная на основе делегатов. Стандартные события можно разделить по областям применения:

1. События пользовательского интерфейса (WinForms/WPF):

  • Click, MouseDown, MouseUp, MouseMove — взаимодействие с мышью.
  • KeyDown, KeyUp, KeyPress — обработка нажатий клавиш.
  • TextChanged — изменение текста в TextBox.
  • SelectedIndexChanged — изменение выбора в ComboBox или ListBox.

2. События жизненного цикла объектов:

  • Load, Shown, FormClosing, FormClosed — для окон Windows Forms.
  • Page_Load, Page_Init — в классическом ASP.NET Web Forms.

3. События компонентов .NET:

  • Elapsed — у класса System.Timers.Timer.
  • Changed, Created, Deleted, Renamed — у FileSystemWatcher для отслеживания файловой системы.
  • CollectionChanged — у ObservableCollection<T> для уведомлений об изменении коллекции (используется в WPF привязке данных).

Почему используется шаблон EventHandler? Он стандартизирован и обеспечивает безопасность типов. Второй параметр e наследуется от EventArgs и может содержать дополнительную информацию о событии.

// Пример объявления и вызова собственного события
public class OrderProcessor
{
    // 1. Объявление события с использованием обобщенного делегата EventHandler<T>
    public event EventHandler<OrderProcessedEventArgs> OrderProcessed;

    public void ProcessOrder(Order order)
    {
        // Логика обработки...
        // 2. Вызов события (проверка на null обязательна!)
        OrderProcessed?.Invoke(this, new OrderProcessedEventArgs { OrderId = order.Id, Time = DateTime.Now });
    }
}

// 3. Класс для аргументов события
public class OrderProcessedEventArgs : EventArgs
{
    public int OrderId { get; set; }
    public DateTime Time { get; set; }
}

// 4. Подписка на событие
processor.OrderProcessed += (sender, e) => 
{
    Console.WriteLine($"Order {e.OrderId} processed at {e.Time}");
};

Важно: Всегда используйте ?.Invoke() для потокобезопасного вызова события. Для событий без дополнительных данных используйте стандартный делегат EventHandler.