In C#, delegates and events are fundamental concepts that enable powerful and flexible communication between objects, especially in event-driven programming. They are often used together, with delegates serving as the foundation for events.
Let's break them down:
At its core, a delegate in C# is a type-safe function pointer. This means it's a reference type that holds a reference to a method (or multiple methods). Think of it like a variable that can store a method instead of data.
+=
-=
Analogy: Imagine a TV remote control. The remote (delegate) doesn't perform the action itself, but it has buttons (methods) that, when pressed, instruct the TV (target object) to perform an action like "increase volume."
public delegate void MyDelegate(string message);
This declares a delegate named MyDelegate that can point to any method that takes a string as a parameter and returns void.
MyDelegate
string
void
using System; // 1. Declare a delegate public delegate void MessageHandler(string message); public class Program { // A method that matches the delegate's signature public static void PrintToConsole(string msg) { Console.WriteLine($"Console Output: {msg}"); } public static void PrintToFile(string msg) { // In a real application, this would write to a file Console.WriteLine($"File Output (simulated): {msg}"); } public static void Main(string[] args) { // 2. Create an instance of the delegate and assign a method MessageHandler handler = PrintToConsole; // 3. Invoke the delegate handler("Hello from the delegate!"); // Calls PrintToConsole // Multicast delegate: Add another method handler += PrintToFile; // Invoke the delegate again (now calls both methods) handler("This message goes to both!"); // Remove a method handler -= PrintToConsole; // Now only PrintToFile will be called handler("Only to file now!"); } }
An event in C# is a special type of delegate that provides a controlled mechanism for one class (the publisher) to notify other classes (the subscribers or listeners) when something of interest occurs. Events are a core part of implementing the Observer design pattern.
EventHandler
EventHandler<TEventArgs>
On<EventName>
OnButton_Click
Analogy: Think of a fire alarm system. The alarm (event) is triggered when smoke is detected (publisher). The fire department, building management, and occupants (subscribers) are all notified when the alarm rings, but they don't directly control when the alarm goes off.
public event MyDelegate MyEvent;
Here, MyDelegate is a previously defined delegate type.
using System; // 1. Define a delegate for the event (can also use built-in EventHandler) public delegate void TemperatureChangeHandler(object sender, TemperatureEventArgs e); // Custom EventArgs class to pass data with the event public class TemperatureEventArgs : EventArgs { public double NewTemperature { get; } public TemperatureEventArgs(double newTemperature) { NewTemperature = newTemperature; } } // Publisher class: Monitors temperature and raises an event public class Thermostat { private double _currentTemperature; // 2. Declare an event using the delegate public event TemperatureChangeHandler TemperatureChanged; public double CurrentTemperature { get { return _currentTemperature; } set { if (_currentTemperature != value) { _currentTemperature = value; // 3. Raise the event when the temperature changes OnTemperatureChanged(new TemperatureEventArgs(value)); } } } // Protected virtual method to raise the event protected virtual void OnTemperatureChanged(TemperatureEventArgs e) { // Check if there are any subscribers before invoking TemperatureChanged?.Invoke(this, e); } } // Subscriber class: Reacts to temperature changes public class Heater { public void TurnOn(object sender, TemperatureEventArgs e) { if (e.NewTemperature < 20) { Console.WriteLine($"Heater: Temperature dropped to {e.NewTemperature}°C. Turning ON."); } } } public class AirConditioner { public void TurnOff(object sender, TemperatureEventArgs e) { if (e.NewTemperature > 25) { Console.WriteLine($"AC: Temperature rose to {e.NewTemperature}°C. Turning ON."); } } } public class Program { public static void Main(string[] args) { Thermostat thermostat = new Thermostat(); Heater heater = new Heater(); AirConditioner ac = new AirConditioner(); // 4. Subscribers register for the event thermostat.TemperatureChanged += heater.TurnOn; thermostat.TemperatureChanged += ac.TurnOff; Console.WriteLine("Initial Temperature: " + thermostat.CurrentTemperature); thermostat.CurrentTemperature = 18; // Heater turns on thermostat.CurrentTemperature = 28; // AC turns on thermostat.CurrentTemperature = 22; // Neither turns on } }
delegate
event
In summary, delegates are the underlying mechanism that allows you to treat methods as objects and pass them around. Events are a specific and controlled use case of delegates, providing a structured way to implement notification systems and achieve loose coupling in your C# applications.
Comments - Beta - WIP