How to use closures in C#
By FoxLearn 1/5/2025 10:12:34 AM 55
Delegates, which are type-safe function pointers matching a specific signature, are used for callbacks and event handling.
Closures as First-Class Functions in C#
A closure in C# is a first-class function tied to its lexical environment, allowing it to access free variables from that environment. C# treats functions like first-class data types, enabling them to be assigned, invoked, or passed around like other data types.
Closure Examples in C#
You can write a closure using an anonymous method as shown below:
Func<int, int> multiplyByTwo = delegate (int number) { return number * 2; };
Alternatively, you can create a closure using a lambda expression:
Func<int, int> multiplyByTwo = number => number * 2;
Both snippets create a method that accepts an integer as a parameter and returns its double.
Here’s how you can invoke these closures:
int result = multiplyByTwo(5); // Output: 10
Now, let’s explore closures capturing non-local variables.
int y = 20; Action displayValue = delegate { Console.WriteLine($"The value of the non-local variable y is: {y}"); }; displayValue();
The same can be achieved using a lambda expression:
int y = 20; Action displayValue = () => { Console.WriteLine($"The value of the non-local variable y is: {y}"); }; displayValue();
In both cases, the output will be:
The value of the non-local variable y is: 20
Closures Capture Variables, Not Values
Closures in C# are bound to the variables in their lexical environment, not just their values.
int z = 30; Action showValue = delegate { Console.WriteLine($"The value of z is: {z}"); }; z = 50; showValue();
When executed, the output will be:
The value of z is: 50
This behavior occurs because the closure references the variable z
itself, not its original value.
How Do C# Closures Work?
When the C# compiler encounters a closure that captures local variables beyond its original scope, it promotes the delegate and its associated variables into a compiler-generated class. This ensures the variables remain accessible even if their original scope ends.
[CompilerGenerated] private sealed class <>c__DisplayClass0_0 { public int z; internal void <M>b__0() { Console.WriteLine($"The value of z is: {z}"); } }
This mechanism allows closures to keep variables alive as long as the closure itself is callable. Originally from functional programming, closures now play a significant role in object-oriented languages like C#, simplifying the implementation of delegates.
- How to fix 'Failure sending mail' in C#
- How to Parse a Comma-Separated String from App.config in C#
- How to convert a dictionary to a list in C#
- How to retrieve the Executable Path in C#
- How to validate an IP address in C#
- How to retrieve the Downloads Directory Path in C#
- C# Tutorial
- Dictionary with multiple values per key in C#