C# & .NET Framework Collections & LINQ Magic
💡
Exercise 44

Lambdas & Delegates 25 XP Hard

Ctrl+Enter Run Ctrl+S Save

The City's Automated Response System 🚨

A modern city needs an automated response system — when a fire is detected, a callback dispatches the fire team; when a building is completed, subscribers are notified. In C#, this is powered by delegates, lambda expressions, and events. These are the building blocks of event-driven programming that make .NET so powerful for everything from desktop apps to microservices.

Delegates — Type-Safe Function Pointers

A delegate is a type that represents a reference to a method with a specific signature. Think of it as a contract: "any method matching this signature can be assigned here."

// Declare a delegate type delegate void AlertHandler(string message); // A method that matches the delegate signature static void ShowAlert(string msg) { Console.WriteLine($"Alert: {msg}"); } // Using it AlertHandler handler = ShowAlert; handler("Fire detected!"); // Output: Alert: Fire detected!

Lambda Expressions — Concise Inline Functions

Lambda expressions (introduced in C# 3.0) let you write anonymous methods inline using the => ("goes to") operator. They are the heart of LINQ and modern C#:

// Expression lambda (single expression, return is implicit) Func<int, int> square = x => x * x; Console.WriteLine(square(5)); // 25 // Statement lambda (multiple statements, needs braces and explicit return) Func<int, int, int> add = (a, b) => { int result = a + b; return result; }; // Lambda with no parameters Action greet = () => Console.WriteLine("Hello, Architect!");

Built-in Delegate Types: Action, Func, and Predicate

C# provides three generic delegate types so you rarely need to declare your own:

  • Action<T> — Takes parameters but returns void. Use for side effects (logging, printing).
  • Func<T, TResult> — Takes parameters and returns a value. The last type parameter is always the return type.
  • Predicate<T> — Takes one parameter and returns bool. Used for filtering/testing conditions.
// Action<T> — no return value Action<string> dispatch = team => Console.WriteLine($"Action: Dispatching {team}"); dispatch("team"); // Func<T, TResult> — has a return value Func<int, bool> isPositive = n => n > 0; Console.WriteLine(isPositive(5)); // True // Predicate<T> — specialized bool-returning delegate Predicate<string> startsWithA = s => s.StartsWith("A"); List<string> names = new List<string> { "Alice", "Bob", "Anna" }; List<string> aNames = names.FindAll(startsWithA); // ["Alice", "Anna"]

Multicast Delegates

Delegates can chain multiple methods using +=. When invoked, all chained methods execute in order:

Action<string> emergency = msg => Console.WriteLine($"Log: {msg}"); emergency += msg => Console.WriteLine($"Alert: {msg}"); emergency += msg => Console.WriteLine($"SMS: {msg}"); emergency("Building on fire!"); // Log: Building on fire! // Alert: Building on fire! // SMS: Building on fire!

Events — Controlled Delegate Access

An event is a delegate with access restrictions: only the declaring class can invoke it, but any class can subscribe. This is the foundation of the Observer pattern in .NET:

class CityPlanner { // Declare the event using EventHandler public event Action<string> BuildingCompleted; public void CompleteBuilding(string name) { Console.WriteLine($"Building {name} is done!"); BuildingCompleted?.Invoke(name); // Safely invoke } } // Subscribe to the event var planner = new CityPlanner(); planner.BuildingCompleted += name => Console.WriteLine($"Event: {name} completed!"); planner.CompleteBuilding("Sky Tower"); // Building Sky Tower is done! // Event: Sky Tower completed!

Time to build the city's automated response system using all of these concepts, Architect!

📋 Instructions
**Build the City's Automated Response System!** 1. Create a `delegate void AlertDelegate(string message)` (declare outside `Program` class or at class level) 2. Create a static method `ShowAlert(string message)` that prints `"Alert: {message}"` 3. In `Main`, assign `ShowAlert` to an `AlertDelegate` variable and call it with `"Fire detected!"` 4. Create an `Action` called `dispatch` that prints `"Action: Dispatching {value}"`; call it with `"team"` 5. Create a `Predicate` called `needsInspection` that returns `true` if a value is greater than 20 6. Create a `List` with values `{10, 25, 30, 15, 40}` and use `FindAll(needsInspection)` — print `"Filter: {count} buildings need inspection"` where `count` is the result count 7. Create an `Action` called `onComplete`, assign it a lambda that prints `"Event: {value}"` — call it with `"Building completed!"` 8. Print `"All systems operational"`
Declare the delegate as `delegate void AlertDelegate(string message);` before the class. Assign it with `AlertDelegate alert = ShowAlert;` then call `alert("Fire detected!")`. For the Predicate, `Predicate<int> p = n => n > 20;` and `list.FindAll(p)` returns a filtered list. `Action<string>` takes a string and returns void.
main.py
Hi! I'm Rex 👋
Output
Ready. Press ▶ Run or Ctrl+Enter.