Could you please explain me the reason of the following situation.
Today I wrote the code (only variables names are changed):
private void Foo()
{
int firstInteger, secondInteger;
const string firstStringValue = "1", secondStringValue = "2";
if (!string.IsNullOrWhiteSpace(firstStringValue) && int.TryParse(firstStringValue, out firstInteger) &&
!string.IsNullOrWhiteSpace(secondStringValue) && int.TryParse(secondStringValue, out secondInteger))
{
// Using firstInteger and secondInteger here
firstInteger++;
secondInteger++;
}
}
Everything was fine until I decided to move the if condition to a variable:
private void Foo()
{
int firstInteger, secondInteger;
const string firstStringValue = "1", secondStringValue = "2";
bool firstIntegerAndSecondIntegerAreSpecified =
!string.IsNullOrWhiteSpace(firstStringValue) && int.TryParse(firstStringValue, out firstInteger) &&
!string.IsNullOrWhiteSpace(secondStringValue) && int.TryParse(secondStringValue, out secondInteger);
if (firstIntegerAndSecondIntegerAreSpecified)
{
// Use firstInteger and secondInteger here
firstInteger++;
secondInteger++;
}
}
Now the compiler underlines firstInteger and secondInteger variables with error "Local variable might not be initialized before accessing".
But why? The only thing I made is refactored the code a bit. And as I see it the logic is the same.
The compiler (or rather, the specification) doesn't spot the relationship between the value of firstIntegerAndSecondIntegerAreSpecified
and the calls to int.TryParse
. In the first form, it could work out that execution would only enter the body if both calls to int.TryParse
had executed, and therefore both had definitely assigned values (due to the out
parameters). Therefore there was no problem in the if
block.
The rules for definite assignment don't cover the idea that firstIntegerAndSecondIntegerAreSpecified
will only be true if both calls have been made, therefore in the body of the if
block, the variables still aren't definitely assigned, hence the error.
The compiler is not built to be clever enough to figure out that a true value in the boolean variable ensures that the values in the integer are set. The compiler only tracks execution paths, not varaible values.
In the first case the compiler knows that it's impossible to enter the if statement without the TryParse
calls setting the variables. In the second case the if statement is detached from the TryParse
calls, so the compiler would have to track the variable value to figure out the relation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With