C# Delegates and Events Explained
Delegates and events are important features of C# used to create flexible communication between objects. They are commonly used for callbacks, notifications, event-driven applications, and user interface programming.
What is a Delegate in C#?
A delegate is a type-safe reference to a method. It allows a method to be passed as a parameter and executed later.
delegate void MessageHandler(string message);
static void ShowMessage(string message)
{
Console.WriteLine(message);
}
MessageHandler handler = ShowMessage;
handler("Hello C#");
Why Use Delegates?
- Pass methods as parameters
- Create callback functionality
- Separate behavior from implementation
- Build flexible application components
- Support event-driven programming
Using a Delegate as a Callback
A callback allows one method to receive another method and execute it when a specific operation is completed.
static void Process(string name, MessageHandler callback)
{
Console.WriteLine($"Processing {name}");
callback("Processing completed");
}
Process("Order", ShowMessage);
Multicast Delegates
A delegate can reference multiple methods. When invoked, each subscribed method is called in sequence.
MessageHandler handler = ShowMessage;
handler += message => Console.WriteLine($"Log: {message}");
handler("Operation completed");
Built-in Action Delegate
Action is a built-in delegate type used for methods that do not return a value.
Action<string> print = message => Console.WriteLine(message);
print("Hello from Action");
Built-in Func Delegate
Func represents a delegate that returns a value. The final generic type parameter represents the return type.
Func<int, int, int> add = (a, b) => a + b;
int result = add(10, 20);
What is an Event?
An event provides a controlled way for one object to notify other objects when something happens. Events are commonly used with event handlers.
class Button
{
public event EventHandler Clicked;
public void Click()
{
Clicked?.Invoke(this, EventArgs.Empty);
}
}
Subscribing to an Event
Another object can subscribe to an event using the += operator. The subscribed method runs whenever the event is raised.
Button button = new Button();
button.Clicked += (sender, args) =>
{
Console.WriteLine("Button clicked");
};
button.Click();
Removing an Event Handler
An event handler can be removed using the -= operator. This is useful when a subscriber should no longer receive notifications.
EventHandler handler = (sender, args) =>
{
Console.WriteLine("Event received");
};
button.Clicked += handler;
button.Clicked -= handler;
Delegate vs Event
| Feature | Delegate | Event |
|---|---|---|
| Purpose | Reference and invoke methods | Notify subscribers |
| Common Use | Callbacks | Application notifications |
| Invocation | Can be invoked by code holding the delegate | Normally raised by the declaring type |
| Subscription | Assignment or += depending on use | Uses += and -= |
Custom Event Example
class OrderService
{
public event EventHandler OrderCompleted;
public void CompleteOrder()
{
Console.WriteLine("Order completed");
OrderCompleted?.Invoke(this, EventArgs.Empty);
}
}
OrderService service = new OrderService();
service.OrderCompleted += (sender, args) =>
{
Console.WriteLine("Sending confirmation email...");
};
service.CompleteOrder();
Common Delegate Types
| Type | Purpose | Example |
|---|---|---|
| Action | Method with no return value | Action |
| Func | Method with a return value | Func |
| Predicate | Returns true or false | Predicate |
| Custom Delegate | Define a specific method signature | delegate void Handler() |
Real-World Applications
- Button click handling
- Notification systems
- Logging callbacks
- Payment completion events
- Background task notifications
- Game event systems
- UI application events
Common Mistakes to Avoid
- Forgetting to unsubscribe from long-lived events
- Creating custom delegates when Action or Func is sufficient
- Raising events without checking for subscribers
- Putting too much logic inside event handlers
- Using events when a simple method call is clearer
Advanced Concepts
- EventHandler
- Lambda expressions
- Anonymous methods
- Multicast delegates
- Callback patterns
- Weak event patterns
Practice Exercises
- Create a custom delegate
- Build a calculator using Func
- Create an event for order completion
- Subscribe multiple handlers to an event
- Remove an event handler
- Build a simple notification system
Conclusion
Delegates provide a flexible way to reference and pass methods, while events provide a structured mechanism for notifying subscribers. Together, they form an important foundation for callbacks and event-driven programming in C#.