Variable scope in C #: doesn't work as expected

Consider this code

class Program
{
    static void Main(string[] args)
    {            
        string str;
        int x;

        for (x = 1; x < 10; x++)
        {
            str = "this";
        }

        Console.WriteLine(str);
        Console.ReadLine();
    }
}

      

When I compile I get: Error Using unassigned local variable 'str' (I understand this part)

If I change to for loop if it works fine. why so (confused here)?

class Program
{
    static void Main(string[] args)
    {            
        string str;
        int x;

        if (true)
        {
            str = "this";
        }

        Console.WriteLine(str);
        Console.ReadLine();
    }
}

      

What is the reason for this different behavior? I expected this to give the same result in both situations.

What am I doing wrong?

+3


source to share


3 answers


With static analysis, the compiler knows exactly what your statement if

will run and what will be assigned str

.

Change your second example to

class Program
{
    static void Main(string[] args)
    {            
        string str;
        int x;
        bool b = true; // With "const bool" it would work, though

        if (b)
        {
            str = "this";
        }

        Console.WriteLine(str);
        Console.ReadLine();
    }
}

      



and you will have the same behavior as a loop for

.

The compiler doesn't know for sure that your loop for

will execute, even if you know it will, so it will tell you about the unrecognized variable. A more sophisticated compiler can see that your variable is fine in this case, but handling all such cases is a very difficult problem.

If x

was a constant (which doesn't make sense in a loop for

, since you want to increment it), the compiler will be able to see that 1 is indeed less than 10, and this will not warn about an unused variable. Of course, the loop will run forever, but I'm just saying this to emphasize that the compiler can only be sure about constants.

+8


source


The reason is that in the first case, the compiler considers the case where the loop is never executed:

for (x = 1; x < 10; x++)
{
    str = "this";
}

      

Thus, it is assumed that it str

can remain uninitialized.




In the second case, the condition is always true

, so the compiler thinks that it is str

always initialized:

if (true)
{
    str = "this";
}

      

+6


source


The compiler cannot be sure that the loop for

will actually iterate. It can loop 0 times. The operator if(true)

is known to the compiler for unconditional execution.

While a theoretically advanced compiler might reason that the first block of code is in fact unconditionally executed, there is generally no solution to the problem (you run into a halting problem). The compiler is forced to use heuristics to reasonably guess if a given statement is available. If it states that the path is not available, you can confidently know that it is not available. If it says that it is available, it may be available, or it may be false.

+2


source







All Articles