Search code examples
c#loopssecurityvariablesresources

Resource of Cost of Declaring Variables and Scope


I'm at the beginning of my journey learning C#, I'm mid-way through the Microsoft Learn syllabus. I recently encountered a lesson where they stated it's best for security and resource management to give variables as little scope as possible. I wanted to know whether repeated declaring a variable has an impact on resources used by the system. For example:

Code 1:

int i = 0;
int j = 0;

while (i < 10)
{
    Console.WriteLine("Sublist");
    while (j < 3)
    {
        Console.WriteLine($"Entry: {j}");
        j++;
    }
    i++;
}

vs

Code 2:

int i = 0;

while (i < 10)
{
    int j = 0;
    Console.WriteLine("Sublist");
    while (j < 3)
    {
        Console.WriteLine($"Entry: {j}");
        j++;
    }
    i++;
}

Thanks in advance for any and all responses.


Solution

  • Jim (comments) is right that cognitive load is a more important factor here. Splitting large methods into smaller methods can help greatly.

    When talking about local variables inside a method, we need to be clear about two different things:

    1. overhead of the variable
    2. overhead of the lifetime an object reached by a variable

    The problem is: the compiler and runtime/GC are smart, so usually these are only real factors in niche cases.

    In terms of overhead of the variable: usually, this is a non-issue, as the variable will occupy the same local declaration in the IL regardless of our "declaration scopes" that only exist in the weak human meatsack world. But there are exceptions:

    • if a variable is "captured" into a delegate/lambda or similar, the scope is pivotal in defining the capture-context used by the delegate, which can have an impact on allocations but also correctness (for with lambdas is a huge cause of bugs)
    • stackalloc space, if moved inside a loop, usually unnecessarily, can burn through stack space at a frightening rate (stackalloc is very rare in most code!)

    When talking about object lifetimes: the GC can see if you don't read from a local again, so if you've read the local for the last time, the scope doesn't matter (again: declaration scopes only exist in meatsack space). However! If there are lifetime concepts like using in play, this does matter, and changing it changes the behaviour - this can be for better or for worse, and only you know what the lifetime should be.

    Side note: I think it is a stretch to say that there is a genuine security angle here.