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?
source to share
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.
source to share
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";
}
source to share
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.
source to share