Courses/C#/Delegates & Events

    Delegates & Events

    Lesson 13 • Expert Track

    Build event-driven programs with delegates, Action, Func, and the publisher-subscriber pattern.

    What You'll Learn

    • • Declare and use custom delegates
    • • Use built-in Action, Func, and Predicate delegates
    • • Create events with EventHandler<T>
    • • Implement the publisher-subscriber (pub/sub) pattern
    • • Pass functions as parameters for flexible, decoupled code

    Real-World Analogy

    A delegate is like a job posting — it describes the skills needed (parameters and return type), and any qualified method can fill the role. An event is like a newspaper subscription — the publisher sends notifications, and subscribers react however they want.

    Running C# Locally: Install the .NET SDK or use dotnetfiddle.net.

    Custom Delegates

    A delegate is a type that represents a reference to a method with a specific signature. You can assign any matching method to a delegate and invoke it like a function.

    Delegates — Type-Safe Function Pointers

    Create a delegate and pass different methods as parameters.

    Try it Yourself »
    C#
    using System;
    
    // A delegate is a type-safe function pointer
    delegate int MathOperation(int a, int b);
    
    class Program
    {
        static int Add(int a, int b) => a + b;
        static int Multiply(int a, int b) => a * b;
        static int Subtract(int a, int b) => a - b;
    
        static void Main()
        {
            // Assign a method to a delegate
            MathOperation op = Add;
            Console.WriteLine($"Add(3, 5) = {op(3, 5)}");
    
            // Re-assign to a different method
            op = Multiply;
            Console.W
    ...

    Action, Func & Predicate

    C# provides built-in generic delegates so you rarely need custom ones. Action<T> is for void methods, Func<T, TResult> returns a value, and Predicate<T> returns bool.

    Action, Func & Predicate

    Use built-in delegates with lambdas for filtering and transforming.

    Try it Yourself »
    C#
    using System;
    using System.Collections.Generic;
    
    class Program
    {
        static void Main()
        {
            // Action<T> — delegate that returns void
            Action<string> greet = name => Console.WriteLine($"Hello, {name}! 👋");
            greet("Alice");
            greet("Bob");
    
            // Func<T, TResult> — delegate that returns a value
            Func<int, int, int> add = (a, b) => a + b;
            Func<int, int, int> max = (a, b) => a > b ? a : b;
            Console.WriteLine($"\nadd(3, 5) = {add(3, 5)}");
      
    ...

    Common Mistakes

    • Invoking null events: Always use MyEvent?.Invoke() with null-conditional. If no subscribers, the event is null.
    • Using events vs delegates: Events add access restrictions — only the declaring class can raise them. Use events for pub/sub, delegates for callbacks.
    • Memory leaks: Always unsubscribe (-=) from events when an object is done, especially in long-lived applications.

    Events — Publisher/Subscriber Pattern

    Events let a class notify other classes when something happens. The publisher raises the event, and any number of subscribers react — without the publisher knowing anything about them.

    Events — Order Processing System

    Build an event-driven order system with multiple subscribers.

    Try it Yourself »
    C#
    using System;
    
    // Custom EventArgs for extra data
    class OrderEventArgs : EventArgs
    {
        public string OrderId { get; }
        public decimal Total { get; }
    
        public OrderEventArgs(string orderId, decimal total)
        {
            OrderId = orderId;
            Total = total;
        }
    }
    
    class OrderProcessor
    {
        // Declare an event using EventHandler<T>
        public event EventHandler<OrderEventArgs> OrderPlaced;
        public event EventHandler<OrderEventArgs> OrderShipped;
    
        public void PlaceOrder(string 
    ...

    Pro Tips

    • 💡 Prefer Action and Func over custom delegates — less boilerplate.
    • 💡 Use EventHandler<TEventArgs> for events instead of raw delegates.
    • 💡 Lambda expressions (=>) are the most concise way to create delegate instances.
    • 💡 Events enforce encapsulation — only the owner class can invoke them.

    Lesson Complete! 🎉

    You now understand delegates and events — the foundation of event-driven C#. Next: reading and writing files with System.IO.

    Sign up for free to track which lessons you've completed and get learning reminders.

    Previous

    Cookie & Privacy Settings

    We use cookies to improve your experience, analyze traffic, and show personalized ads. You can manage your preferences below.

    By clicking "Accept All", you consent to our use of cookies for analytics and personalized advertising. You can customize your preferences or reject non-essential cookies.

    Privacy PolicyTerms of Service