C# / CHAPTER 10

Delegates and captured state

Intermediate

Pass behavior while making its dependencies visible.

By the end of this chapter

  • Read Func and Action contracts
  • Trace captured variables
  • Keep callbacks free of accidental shared state

The idea

A delegate is a typed reference to callable behavior. Func<int,int> accepts an integer and returns an integer; Action<int> returns no value. Passing a transformation can remove duplicated loops while keeping the operation explicit. A delegate’s type describes its parameters and result, but does not promise that the body is pure or free of exceptions.

A lambda can capture local variables from its surrounding scope. It generally reads the captured variable’s current value when called, rather than a frozen value from creation time. This is useful for deliberate state but can surprise code that builds callbacks and invokes them later. If each callback should retain a different loop value, create a separate local copy in the loop body.

C# example
using System;
int offset = 2;
Func<int, int> shift = n => n + offset;
offset = 5;
Console.WriteLine(shift(3));
Result
8

The lambda reads the updated captured offset when it executes.

Try it yourself

Write a transformation helper taking Func<int,int> and returning a new array without changing its input.

Use your own editor for this exercise. Runnable challenges on CodeQuest are available for JavaScript, Python, and SQL.

CHECK YOUR UNDERSTANDING

Chapter checkpoint

Which delegate type accepts one int and returns bool?