# Delegates, Lambdas and Events — C#/.NET

Source: https://www.skillbyai.com/en/dotnet/t-delegates

> Pass behaviour as data with Func, Action, lambdas and events.

## Functions as values

A **delegate** is a type-safe reference to a method. The BCL's generic delegates cover most needs: **`Func<T1, ..., TResult>`** returns a value, **`Action<T1, ...>`** returns nothing, and **`Predicate<T>`** returns a `bool`. **Lambda expressions** create delegate instances inline: `x => x * 2`, `(a, b) => a + b`. Lambdas can **capture** variables from the enclosing scope (closures); captured variables are shared, not copied, so changing them later affects the lambda. Lambdas are everywhere: LINQ, callbacks, configuration (`options => { ... }`), and the `static` modifier (`static x => x * 2`) prevents accidental captures. **Events** build on delegates for the publisher-subscriber pattern: a class declares `public event EventHandler<OrderPlacedEventArgs>? OrderPlaced;`, outside code can only `+=` and `-=` handlers, and only the declaring class can raise it. Forgetting to unsubscribe from long-lived publishers is a classic memory leak.

## Func, Action and an event

The discount rule is passed in as a function, so callers choose the policy.

```cs
Func<decimal, decimal> festiveDiscount = price => price * 0.9m;
Action<string> log = msg => Console.WriteLine($"[{DateTime.Now:T}] {msg}");

decimal Checkout(decimal price, Func<decimal, decimal> discount) => discount(price);
log($"Pay {Checkout(1000m, festiveDiscount)}");

var shop = new Shop();
shop.OrderPlaced += (_, e) => log($"Order {e.OrderId} placed");
shop.Place("o-1001");

public class Shop
{
    public event EventHandler<OrderPlacedEventArgs>? OrderPlaced;
    public void Place(string id) => OrderPlaced?.Invoke(this, new OrderPlacedEventArgs(id));
}
public record OrderPlacedEventArgs(string OrderId);
```

## Leaving your phone number

Subscribing to an event is leaving your number with a shop: "call me when the stock arrives". If you move away and never cancel, the shop keeps your number forever, which in .NET means it keeps your object alive.

**Quiz:** Which delegate type fits a method that takes a string and returns nothing?

- [x] Action<string>
- [ ] Func<string>
- [ ] Predicate<string>
- [ ] Func<string, bool>

*Answer:* Action<string>. Action<T> represents methods with parameters and no return value.
