Local Functions are introduced in C# 7.0, you can read more about it here. In C# 8.0, these Local Functions are improvised so that it will work with more performance-driven when passing parameters from its containing method.

For example, let’s see the below code block.

public void PrintName(string name)
{
    Console.WriteLine($"You Name is: {name}");
    SayHello();

    void SayHello()
    {
        Console.WriteLine($"Hello {name}!");
    }
}

With the above code block, we are trying to print the name as passed to the method PrintName as a parameter and also greeting “Hello” to the same name. Here, we are using the same name parameter from the calling method in the local function.

At Runtime, when it starts executing PrintName() method, it will keep this information to the Stack memory including the variables scoped for this method. Similarly, in the case of SayHello(). But, here as we are using the parent variables, the runtime will copy these variables in to SayHello() stack memory. It means we are copying these variables to local variables. In our case, we are passing only name string variable to the local function, we cannot see much performance but when we are passing huge objects we can feel the performance.

In C# 8.0, we addressed this issue by declaring the local functions as static. As we are ware static methods won’t be allocated separate memory in each object and same in its variables scoped to it.

By using static local functions, we can rewrite the same logic as below

public void PrintName(string name)
{
    Console.WriteLine($"You Name is: {name}");
    SayHello(name);

    static void SayHello(string name)
    {
        Console.WriteLine($"Hello {name}!");
    }
}

Here, we are passing the name variable as a parameter to the static local function. This way, the local functions do not depend on their calling variables and perform well at runtime with its own scope of variables/objects.

Happy Coding 🙂