Delegates, Func, Action, and Predicates
On this page
Functional C#: Delegates & Actions
A Delegate is a type-safe function pointer. It allows you to pass a "Method" as a parameter to another method. This is the foundation of LINQ, Events, and modern asynchronous callbacks.
1. The Trio: Func, Action, and Predicate
You rarely need to define custom delegates anymore. Microsoft provided three generic wrappers that cover 99% of use cases.
- Action: For methods that return
void. - Func<T, TResult>: For methods that return a value.
- Predicate<T>: A Func that specifically returns a
bool.
// 1. An action that takes a string
Action<string> log = msg => Console.WriteLine(msg);
// 2. A func that takes two ints and returns an int
Func<int, int, int> add = (a, b) => a + b;
// 3. Using them as parameters
public void ProcessData(int val, Action<int> callback)
{
callback(val * 2);
}
2. Multicast Delegates
A single delegate can hold references to multiple methods. When you call the delegate, all methods fire in sequence. This is how the Observer Pattern is implemented in C# via Events.
4. Interview Mastery
Q: "What is a Closure in C# Lambda expressions?"
Architect Answer: "A Closure occurs when a lambda expression 'captures' a variable from its outer scope. Even if that outer variable is a local variable on the stack that should have been destroyed, the C# compiler cleverly generates a hidden class to store that variable on the heap, ensuring it stays alive as long as the lambda exists. Be careful: capturing large objects in closures can prevent the Garbage Collector from cleaning them up, leading to memory leaks."