0Pricing
C# Academy · Lesson

Static Local Functions

Prevent captures for clarity and performance.

Static Local Functions is a free C# Academy lesson on CoddyKit — lesson 3 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the C# Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

Static Local Functions

Marking a local function static forbids it from capturing any enclosing variables or this. This makes the function self-contained, clearer, and free of hidden closure allocations.

Declaring a static Local Function

Add the static modifier before the return type. The function may still take parameters and return values; it just cannot reach outer locals.

using System;

public class Program
{
    public static void Main()
    {
        static int Square(int n) => n * n; // captures nothing

        Console.WriteLine(Square(6));
    }
}

No Capturing Allowed

A static local function cannot use enclosing locals. Everything it needs must be passed in as a parameter, which makes its inputs explicit.

using System;

public class Program
{
    public static void Main()
    {
        int factor = 3;
        // factor must be passed in, not captured
        static int Scale(int n, int f) => n * f;

        Console.WriteLine(Scale(5, factor));
    }
}

Avoiding Hidden Allocations

Non-static local functions that capture variables may allocate a hidden closure object. A static local function never captures, so it avoids that allocation entirely.

using System;

public class Program
{
    public static void Main()
    {
        // Pure helper, no closure object created
        static bool IsEven(int n) => n % 2 == 0;

        for (int i = 0; i < 5; i++)
            Console.WriteLine(i + ": " + IsEven(i));
    }
}

Self-Documenting Intent

The static keyword signals to readers that the helper depends only on its arguments. That guarantee makes the function easier to reason about and test.

using System;

public class Program
{
    public static void Main()
    {
        static int Clamp(int value, int lo, int hi)
            => value < lo ? lo : value > hi ? hi : value;

        Console.WriteLine(Clamp(15, 0, 10));
        Console.WriteLine(Clamp(-3, 0, 10));
    }
}

Compiler Enforces No Capture

If you accidentally reference an enclosing local inside a static local function, the compiler reports an error. This catches unintended dependencies early.

using System;

public class Program
{
    public static void Main()
    {
        int seed = 7;
        // Correct: seed is passed explicitly, not captured
        static int Mix(int x, int s) => x * 31 + s;

        Console.WriteLine(Mix(2, seed));
    }
}

Static Locals With Recursion

Static local functions still support recursion, since calling themselves is not the same as capturing a variable.

using System;

public class Program
{
    public static void Main()
    {
        static int Power(int baseN, int exp)
            => exp == 0 ? 1 : baseN * Power(baseN, exp - 1);

        Console.WriteLine(Power(2, 10));
    }
}

Combining With out Parameters

Like any method, static local functions can use out parameters, which pairs nicely with their no-capture purity for try-parse style helpers.

using System;

public class Program
{
    public static void Main()
    {
        static bool TryParsePositive(string s, out int value)
        {
            value = 0;
            return int.TryParse(s, out value) && value > 0;
        }

        if (TryParsePositive("42", out int n))
            Console.WriteLine("got " + n);
        Console.WriteLine(TryParsePositive("-1", out _));
    }
}

Passing Static Locals as Delegates

Because they capture nothing, static local functions convert to delegates without allocating a closure, which can matter in hot paths.

using System;
using System.Collections.Generic;
using System.Linq;

public class Program
{
    public static void Main()
    {
        static bool IsBig(int n) => n > 100;

        var nums = new List<int> { 50, 150, 200, 10 };
        Console.WriteLine(nums.Count(IsBig));
    }
}

When to Prefer static

Prefer a static local function whenever the helper does not need enclosing state. It documents purity, prevents accidental capture, and can be more efficient. Drop static only when you genuinely need to close over locals.

using System;

public class Program
{
    public static void Main()
    {
        static string Describe(int score)
        {
            if (score >= 90) return "A";
            if (score >= 80) return "B";
            return "C";
        }

        Console.WriteLine(Describe(95));
        Console.WriteLine(Describe(82));
    }
}

Try It Yourself

Write a pure static local function and pass it as a predicate to LINQ. Because it captures nothing, it converts to a delegate without a closure.

using System;
using System.Collections.Generic;
using System.Linq;

public class Program
{
    public static void Main()
    {
        static bool IsLeapYear(int year)
            => (year % 4 == 0 && year % 100 != 0) || year % 400 == 0;

        var years = new List<int> { 1900, 2000, 2004, 2021, 2024 };
        Console.WriteLine(string.Join(", ", years.Where(IsLeapYear)));
    }
}

Quick Check

Recall what static adds to a local function.

Recap

A static local function captures nothing.

  • It cannot use enclosing locals or this; pass data via parameters.
  • It avoids hidden closure allocations.
  • The compiler enforces the no-capture rule, catching accidental dependencies.
  • Prefer it whenever the helper does not need enclosing state.

Frequently asked questions

Is the “Static Local Functions” lesson free?

Yes — the full text of “Static Local Functions” is free to read here on the web, and the C# Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the C# Academy course, upgrade to CoddyKit PRO.

What will I learn in “Static Local Functions”?

Prevent captures for clarity and performance. You practise C# Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start C# Academy?

No prior experience is required. C# Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 3 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “Static Local Functions” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this C# Academy lesson?

Yes. Every C# Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. Declaring Local Functions
  2. Closures and Captured Variables
  3. Static Local Functions
  4. Local Functions vs Lambdas
← Back to C# Academy