Events are built on delegates and implement the observer (publish-subscribe) pattern — one object notifies many others when something happens.
public class Button
{
// Declare the event using EventHandler (built-in delegate)
public event EventHandler? Clicked;
public void Click()
{
Console.WriteLine("Button clicked.");
Clicked?.Invoke(this, EventArgs.Empty); // raise the event
}
}
var btn = new Button();
// Subscribe to the event
btn.Clicked += (sender, e) => Console.WriteLine("Handler 1: reacting to click!");
btn.Clicked += (sender, e) => Console.WriteLine("Handler 2: logging the click.");
btn.Click();
// Button clicked.
// Handler 1: reacting to click!
// Handler 2: logging the click.
public class OrderEventArgs : EventArgs
{
public int OrderId { get; }
public decimal Total { get; }
public OrderEventArgs(int id, decimal total) { OrderId = id; Total = total; }
}
public class OrderService
{
public event EventHandler<OrderEventArgs>? OrderPlaced;
public void PlaceOrder(int id, decimal total)
{
// process order...
OrderPlaced?.Invoke(this, new OrderEventArgs(id, total));
}
}
var svc = new OrderService();
svc.OrderPlaced += (s, e) =>
Console.WriteLine($"Order #{e.OrderId} placed — Total: {e.Total:C}");
svc.PlaceOrder(42, 99.99m);
// Order #42 placed — Total: $99.99