Chapter 18: Delegates, Events, and Lambda Expressions
1. What is a Delegate? (Super Simple Analogy)
Think of a delegate like a phone number or a remote control pointer:
- You have a method (the person who does the work)
- You create a delegate (the phone number) that points to that method
- You can call the delegate → it calls the method (even if you don’t know the method name anymore)
- You can change what the delegate points to → switch who answers the phone!
In C#, a delegate is a type-safe function pointer – it lets you pass methods as parameters, store them in variables, and call them later.
2. Defining and Using a Basic Delegate
Syntax:
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
// 1. Define the delegate type (signature must match the methods) delegate void MyDelegate(string message); // Takes string, returns void // 2. Methods that match the signature class Messenger { public static void SendEmail(string msg) { Console.WriteLine($"📧 Email: {msg}"); } public static void SendSms(string msg) { Console.WriteLine($"📱 SMS: {msg}"); } public static void SendPush(string msg) { Console.WriteLine($"🔔 Push: {msg}"); } } // 3. Usage MyDelegate notifier = Messenger.SendEmail; // Points to SendEmail notifier("Hello from Hyderabad!"); // Calls SendEmail notifier = Messenger.SendSms; // Now points to SendSms notifier("Meeting at 5 PM"); // Calls SendSms // You can also chain them (multicast delegate) notifier += Messenger.SendPush; // Add another method notifier("Dinner plans?"); // Calls ALL three! |
Output:
|
0 1 2 3 4 5 6 7 8 |
📧 Email: Dinner plans? 📱 SMS: Dinner plans? 🔔 Push: Dinner plans? |
3. Events and Event Handlers – The Real Power of Delegates
An event is a special kind of delegate that allows other classes to subscribe (listen) to something happening.
Analogy: A button has a Click event. Any number of methods can subscribe to it (like ShowMessage, SaveData, PlaySound). When the button is clicked → all subscribed methods are called automatically!
Syntax:
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
class Button { // 1. Define the event (using EventHandler or custom delegate) public event EventHandler Clicked; // EventHandler = delegate void (object sender, EventArgs e) public void SimulateClick() { Console.WriteLine("Button was clicked!"); Clicked?.Invoke(this, EventArgs.Empty); // Safely raise the event } } // 2. Event handlers (methods that will be called) class Screen { public void ShowMessage(object sender, EventArgs e) { Console.WriteLine("Screen: Message box popped up! 😊"); } } class Logger { public void LogClick(object sender, EventArgs e) { Console.WriteLine("Logger: Button click recorded at " + DateTime.Now); } } // 3. Usage Button myButton = new Button(); Screen screen = new Screen(); Logger logger = new Logger(); // Subscribe to the event myButton.Clicked += screen.ShowMessage; myButton.Clicked += logger.LogClick; // Unsubscribe if needed // myButton.Clicked -= logger.LogClick; myButton.SimulateClick(); |
Output:
|
0 1 2 3 4 5 6 7 8 |
Button was clicked! Screen: Message box popped up! 😊 Logger: Button click recorded at 1/21/2026 4:46:00 PM |
4. Anonymous Methods and Lambda Expressions (=>) – Modern & Super Clean
Anonymous method (old style – C# 2.0):
|
0 1 2 3 4 5 6 7 8 9 |
myButton.Clicked += delegate(object sender, EventArgs e) { Console.WriteLine("Anonymous: Button clicked!"); }; |
Lambda expression (C# 3.0+ – the modern way – short & beautiful):
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
// Simple lambda myButton.Clicked += (sender, e) => Console.WriteLine("Lambda: Button clicked! 🚀"); // With parameters and body myButton.Clicked += (sender, e) => { Console.WriteLine("Lambda with body:"); Console.WriteLine("Sender: " + sender); }; |
Very common real-world example:
|
0 1 2 3 4 5 6 7 8 9 10 11 |
List<int> numbers = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; // Lambda used everywhere! var evenNumbers = numbers.Where(n => n % 2 == 0).ToList(); // 2,4,6,8,10 numbers.ForEach(n => Console.Write(n + " ")); // Prints all |
5. Func, Action, Predicate – Built-in Generic Delegates
C# provides ready-made generic delegates so you don’t have to define your own every time.
| Delegate | Signature | Use Case | Example |
|---|---|---|---|
| Action | void (params) | Methods that do something | Action<string> log = msg => Console.WriteLine(msg); |
| Action<T> | void (T) | One parameter | Action<int> print = n => Console.WriteLine(n); |
| Func<T> | T () | Returns value, no input | Func<DateTime> now = () => DateTime.Now; |
| Func<T1,T2, TResult> | TResult (T1,T2) | Most common – returns result | Func<int,int,int> add = (a,b) => a+b; |
| Predicate<T> | bool (T) | Returns true/false (test condition) | Predicate<int> isEven = n => n % 2 == 0; |
Real example – Using built-in delegates
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
// Action – do something Action<string> greet = name => Console.WriteLine($"Hello, {name}! 👋"); greet("Webliance"); // Func – return something Func<int, int, int> multiply = (a, b) => a * b; Console.WriteLine(multiply(7, 8)); // 56 // Predicate – test condition Predicate<string> isLong = s => s.Length > 5; Console.WriteLine(isLong("Hyderabad")); // True Console.WriteLine(isLong("Goa")); // False // Used in LINQ List<string> cities = new List<string> { "Hyderabad", "Delhi", "Mumbai", "Chennai" }; var longCities = cities.FindAll(isLong); foreach (string city in longCities) { Console.WriteLine(city); // Hyderabad, Chennai } |
Mini-Project: Event-Driven Notification System
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
class NewsPublisher { public event Action<string> NewsPublished; // Using Action public void PublishNews(string headline) { Console.WriteLine($"Breaking News: {headline}"); NewsPublished?.Invoke(headline); } } class TvChannel { public void OnNews(string headline) { Console.WriteLine($"TV: Showing live coverage of: {headline} 📺"); } } class Newspaper { public void PrintHeadline(string headline) { Console.WriteLine($"Newspaper: Printing front page: {headline} 📰"); } } class SocialMedia { public void PostUpdate(string headline) { Console.WriteLine($"Twitter/X: Posting: {headline} 🔥"); } } // Usage NewsPublisher publisher = new NewsPublisher(); TvChannel tv = new TvChannel(); Newspaper paper = new Newspaper(); SocialMedia social = new SocialMedia(); // Subscribe publisher.NewsPublished += tv.OnNews; publisher.NewsPublished += paper.PrintHeadline; publisher.NewsPublished += social.PostUpdate; // Publish publisher.PublishNews("India wins T20 World Cup 2026! 🏆"); |
Output:
|
0 1 2 3 4 5 6 7 8 9 |
Breaking News: India wins T20 World Cup 2026! 🏆 TV: Showing live coverage of: India wins T20 World Cup 2026! 🏆 📺 Newspaper: Printing front page: India wins T20 World Cup 2026! 🏆 📰 Twitter/X: Posting: India wins T20 World Cup 2026! 🏆 🔥 |
Summary – What We Learned Today
- Delegate → type-safe function pointer (pass methods around)
- Event → special delegate for publish-subscribe pattern
- Lambda expressions (=>) → short, anonymous methods
- Func, Action, Predicate → built-in generics for common signatures
- Multicast → one delegate/event can call multiple methods
- Used everywhere: LINQ, events, async/await, callbacks, Unity events…
Your Homework (Super Fun & Practical!)
- Create a new console project called DelegatesAndEvents
- Create a class TemperatureSensor with:
- Event TemperatureChanged (use Action<double>)
- Method ChangeTemperature(double newTemp) that raises the event
- Create 3 subscribers:
- Display → shows current temperature
- Alarm → beeps if > 40°C
- Logger → logs to console with timestamp
- In Program.cs: Subscribe all 3, change temperature a few times, and see the magic!
Next lesson: LINQ (Language Integrated Query) – we’re going to learn how to query, filter, sort, and transform collections like magic!
You’re doing absolutely fantastic! 🎉 Any part confusing? Want more examples with multicast events or lambdas? Just tell me — I’m right here for you! 💙
