Cody
Cody

Reputation: 2649

Variable scope in c#: Not working 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 Use of unassigned local variable 'str' (I understand this part)

If i change for loop to if then 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 it should give same result in both situations.

What am i doing wrong ?

Upvotes: 3

Views: 226

Answers (3)

dee-see
dee-see

Reputation: 24088

With static analysis, the compiler knows for sure that your if statement will run and that str will be assigned.

Change your 2nd 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 the for loop.

The compiler doesn't know for sure that your for loop will be executed even if you know it will be, so that's why it's telling you about the unassigned variable. A more sophisticated compiler might be able to see that your variable is fine in this case, but handling all such cases is a very complicated problem.

If x was a constant (which makes no sense in a for loop since you want to increment it...) the compiler would be able to see that 1 is indeed smaller than 10 and it wouldn't warn you about the unused variable. Of course the loop would run forever now, but I'm saying this just to highlight that the compiler can only be sure about constants.

Upvotes: 8

AlexD
AlexD

Reputation: 32616

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

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

So it assumes that str may stay uninitialized.


In the second case, the condition is always true, so compiler considers that str is always initialized:

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

Upvotes: 6

Servy
Servy

Reputation: 203847

The compiler cannot be certain that a for loop will actually iterate. It could loop 0 times. An if(true) statement is known to the compiler to unconditionally execute.

While, in theory, a suitably advanced compiler could reason that the first code block does in fact unconditionally execute, solving the problem in the general case is impossible (you run into the Halting Problem). The compiler is forced to use heuristics to take a reasonable guess at whether or not a given statement is reachable. If it states that a path is not reachable you can know with certain that it is not reachable. If it says that it is reachable it may be reachable, or it may be a false positive.

Upvotes: 2

Related Questions