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.

CSHARP
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.

CSHARP
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.

CSHARP
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.

CSHARP
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.

CSHARP
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.

CSHARP
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.

CSHARP
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.

CSHARP
EventHandler handler = (sender, args) =>
{
    Console.WriteLine("Event received");
};

button.Clicked += handler;
button.Clicked -= handler;

Delegate vs Event

FeatureDelegateEvent
PurposeReference and invoke methodsNotify subscribers
Common UseCallbacksApplication notifications
InvocationCan be invoked by code holding the delegateNormally raised by the declaring type
SubscriptionAssignment or += depending on useUses += and -=

Custom Event Example

CSHARP
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

TypePurposeExample
ActionMethod with no return valueAction
FuncMethod with a return valueFunc
PredicateReturns true or falsePredicate
Custom DelegateDefine a specific method signaturedelegate 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#.

Note: Note: Use delegates for method references and callbacks, and use events when one component needs to notify other components about something that happened.