As a C# developer you got used to apply anonymous functions everywhere. Everytime you write a LINQ statement or use a lamdbda expression, you are creating an anonymous function.
But what you maybe are not aware of is that anonymous functions have a performance impact and donāt come cheap:
- Overhead of a delegate invocation (very very small, but it does exist).
- 2 heap allocations if a lambda captures local variable or argument of enclosing method (one for closure instance and another one for a delegate itself).
- 1 heap allocation if a lambda captures an enclosing instance state (just a delegate allocation).
- 0 heap allocations only if a lambda does not capture anything or captures a static state.
One way to limit the number of allocations is through local functions but today I want to focus on another option; using static anonymous functions.
Letās use a really simple example where static anonymous functions can help:
int addition = 1; | |
ApplyFormula(x => x + addition); | |
private void ApplyFormula(Func<int, int> formula) | |
{ | |
var numbers = new[] { 1, 2, 3, 4, 5 }; | |
foreach(var number in numbers) | |
{ | |
formula(number); | |
} | |
} |
In the example above we capture the value āadditionā, causing an unintended allocation. To fix it we can change the implementation to use a static anonymous function. Therefore we have to apply the const
modifier on the variable and add the static
modifier to the lambda:
const int addition = 1; | |
ApplyFormula(static x => x + addition); | |
private void ApplyFormula(Func<int, int> formula) | |
{ | |
var numbers = new[] { 1, 2, 3, 4, 5 }; | |
foreach(var number in numbers) | |
{ | |
formula(number); | |
} | |
} |
Some rules apply when you want to use static anonymous functions:
- A static anonymous function cannot capture state from the enclosing scope. As a result, locals, parameters, and
this
from the enclosing scope are not available within a static anonymous function. - A static anonymous function cannot reference instance members from an implicit or explicit
this
orbase
reference. - A static anonymous function may reference
static
members from the enclosing scope. - A static anonymous function may reference
constant
definitions from the enclosing scope.