Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why declare a local function static in C# 8.0

In C# 8.0, Static Local Functions are announced

Can anyone help enlighten me as to why you would want to declare a local function as static?

The reason given in in the article:

to ensure that local function doesn't capture (reference) any variables from the enclosing scope

But:

  1. I don't understand why would you want to ensure that?
  2. Is there any other reason or benefits to declare it static? (performance maybe?)

The example code given in the article is:

int M()
{
    int y = 5;
    int x = 7;
    return Add(x, y);

    static int Add(int left, int right) => left + right;
}
like image 703
fourbeatcoder Avatar asked Nov 07 '19 09:11

fourbeatcoder


People also ask

Why we declare function as static in C?

Unlike global functions in C, access to static functions is restricted to the file where they are declared. Therefore, when we want to restrict access to functions, we make them static. Another reason for making functions static can be reuse of the same function name in other files.

What is the purpose of static function?

A static function is a member function of a class that can be called even when an object of the class is not initialized. A static function cannot access any variable of its class except for static variables. The 'this' pointer points to the object that invokes the function.

What is the use of static local variable?

A local static variable is a variable, whose lifetime doesn't stop with a function call where it is declared. It extends until the lifetime of a complete program. All function calls share the same copy of local static variables. These variables are used to count the number of times a function is called.

What is the point of a local function?

The local function's purpose is to make your program more readable, and you are prevented from calling the local function by mistake as you cannot call it directly.


Video Answer


4 Answers

I don't understand why would you want to ensure that?

Because it prevents you from shooting yourself in the foot. It forces the local function to be a pure function that does not modify the state of the caller.

This returns false, because the function modifies local variables of its caller:

public bool Is42()
{
    int i = 42;     
    Foo();      
    return i == 42;

    void Foo()
    {
        i = 21;
    }   
}

And this doesn't, because it doesn't even compile:

public bool Is42()
{
    int i = 42;     
    Foo();      
    return i == 42;

    static void Foo()
    {
        i = 21;
    }   
}

It prevents surprises. Of course in these simple examples the benefit isn't immediately clear, because "well it's obvious that Foo() modifies i", but in larger codebases maintained by multiple people and not properly covered by unit tests, this simple modifier prevents grief.

like image 94
CodeCaster Avatar answered Oct 12 '22 03:10

CodeCaster


Capturing variables has a small additional cost as it will generate an internally used type where your captured variables are public fields. Consider a slightly modified example:

int M()
{
    int y = 5;
    int x = 7;
    return Add();

    int Add() => x + y;
}

It will actually translate to something like this:

int M()
{
    int y = 5;
    int x = 7;
    var capturedVars = new <>c__DisplayClass0_0 { x = x, y = y };
    return <M>g__Add|0_0(ref capturedVars);
}

[CompilerGenerated]
private struct <>c__DisplayClass0_0
{
    public int x;
    public int y;
}

[CompilerGenerated]
internal static int <M>g__Add|0_0(ref <>c__DisplayClass0_0 class_Ref1) => 
    (class_Ref1.x + class_Ref1.y);
like image 33
György Kőszeg Avatar answered Oct 12 '22 03:10

György Kőszeg


This answer from CodeCaster and this separate answer from György Kőszeg individually answer different parts of my question, so I'm bringing them both together to form the full picture for the accepted answer:

For Part 1) of my question, @CodeCaster Says:

Because it prevents you from shooting yourself in the foot. It forces the local function to be a pure function that does not modify the state of the caller.

in larger codebases maintained by multiple people and not properly covered by unit tests, this simple modifier prevents grief

So Answer 1 is: Static Local Functions ensure reliable caller method state.

For Part 2) of my question, @György Kőszeg Says:

Capturing variables has a small additional cost as it will generate an internally used type where your captured variables are public fields

And he goes on to give an example of the produced compiler code via reflector.

So Answer 2 is: Static Local Functions prevent variable capturing. Variable capturing comes at a small cost. So there is a small performance boost by declaring the local function static

like image 3
fourbeatcoder Avatar answered Oct 12 '22 01:10

fourbeatcoder


I think this is just to ensure correct usage of the variables used in the local function, as the documentation says. In large and complex methods, it can prevent accidental usage of enclosing scope variables if there are variables with the same name in the local function.

like image 1
Farhad Rahmanifard Avatar answered Oct 12 '22 02:10

Farhad Rahmanifard