C# tutorials > Modern C# Features > C# 6.0 and Later > What are static anonymous functions?

What are static anonymous functions?

Static anonymous functions, introduced in C# 9.0, are anonymous methods (lambdas or anonymous delegates) that prevent capturing variables from the enclosing scope. This means they operate independently of the surrounding context, enhancing code safety and potentially improving performance.

Basic Syntax and Example

The keyword static before the parameter list of the lambda expression signifies a static anonymous function. Inside such a function, you cannot access variables declared outside the function's scope. This restriction is enforced by the compiler. The example demonstrates squaring a number using a static lambda. The commented-out line illustrates the error that occurs when trying to access a variable from the outer scope.

Func<int, int> square = static x => x * x; 

// Attempting to use a variable from the outer scope will result in a compilation error.
int factor = 2; 
//Func<int, int> multiply = static x => x * factor; // Compilation Error: CS8422 Cannot use local variable 'factor' inside a 'static' lambda expression or anonymous method.

Concepts Behind the Snippet

Static anonymous functions enforce closure restrictions. Closures are functions that capture variables from their surrounding environment. By disallowing variable capture, static anonymous functions prevent unintended side effects and make code easier to reason about. This isolation also potentially enables compiler optimizations because the function's behavior is solely determined by its input parameters and local variables.

Real-Life Use Case Section

Imagine processing large datasets where you want to filter based on specific criteria. Using a static anonymous function within a Where LINQ query ensures that the filtering logic is self-contained and doesn't inadvertently access or modify any class-level state (like _threshold in the code example) which could lead to unexpected behavior. The data processing becomes more predictable and maintainable.

using System;
using System.Linq;

public class Example
{
    private int _threshold = 10;

    public void ProcessData(int[] data)
    {
        // Use a static local function to filter data without accidentally using _threshold.
        var filteredData = data.Where(static x => x > 5).ToArray();

        Console.WriteLine(string.Join(", ", filteredData));
    }

    public static void Main(string[] args)
    {
        Example example = new Example();
        example.ProcessData(new int[] { 2, 6, 8, 12, 3, 7 });
    }
}

Best Practices

Use static anonymous functions whenever you don't need to access variables from the enclosing scope. This promotes code clarity and reduces the risk of bugs. Prefer them over regular anonymous functions unless variable capture is explicitly required. This helps make your intentions clear to other developers reading your code.

Interview Tip

Be prepared to explain the concept of closures and how static anonymous functions differ by preventing variable capture. Understand the benefits in terms of code safety, predictability, and potential performance gains. Be able to provide examples of situations where their use is appropriate and where they are not.

When to use them

Use static anonymous functions when:

  1. Your lambda expression doesn't need to access any variables from the enclosing scope.
  2. You want to ensure that the lambda function is pure, meaning its output depends only on its input and has no side effects.
  3. You want to improve code readability and maintainability by explicitly stating that the lambda function is independent of its surrounding context.

Memory footprint

Because static anonymous functions do not capture any variables from the outer scope, they may have a slightly smaller memory footprint compared to regular anonymous functions, especially if the captured scope is large. However, the difference is usually negligible in most real-world scenarios.

Alternatives

The main alternative is a regular anonymous function (lambda expression) without the static keyword. If you need to access variables from the enclosing scope, you must use a regular anonymous function. Alternatively, you could create a named method, either static or instance, and pass that as a delegate. This provides clearer naming and can be useful for more complex logic.

Pros

  • Improved Code Safety: Prevents accidental modification of external variables.
  • Increased Predictability: Makes the function's behavior easier to understand and reason about.
  • Potential Performance Gains: Can enable compiler optimizations.
  • Clearer Intent: Explicitly states that the function is independent of its surrounding context.

Cons

  • Limited Scope: Cannot access variables from the enclosing scope.
  • Requires Careful Consideration: You need to carefully consider whether or not you need to access any external variables before using a static anonymous function.

FAQ

  • What happens if I try to access a variable from the outer scope within a static anonymous function?

    The compiler will generate an error (CS8422) indicating that you cannot use a local variable inside a 'static' lambda expression or anonymous method.
  • Are static anonymous functions automatically more performant than regular anonymous functions?

    Not always. While they have the potential for performance gains due to compiler optimizations, the actual impact depends on the specific scenario and the compiler's ability to optimize the code. The performance difference is often negligible.
  • Can I use static anonymous functions with async/await?

    Yes, you can combine static anonymous functions with async and await, as long as you adhere to the rule that you cannot capture variables from the enclosing scope. The function itself becomes an async function.