I have the following code, which results in a compile error, despite seemingly being correct:
bool aBool = SomePredicate();
if (!aBool && !OutFunction(out int value))
{
return;
}
int result = -1; //other code here...
if (!aBool && SomeCondition(result, value)) // CS0165: Use of unassigned variable 'value'.
{
}
The variable aBool
is not modified between the two conditions, meaning that if aBool
was false during the first check it'll always be assigned.
Otherwise, if aBool
was true, then the variable would never be used, as the expression should end once the first part is evaluated.
Despite this, why does this result in a compile error? (C# 7.3) Additionally, what is the best way to get around it?
Main focus is on the "Why?" part
&&
is a short-circuiting AND
so if !aBool
is evaluated to false
, !OutFunction(out int value)
is never evaluated and the method continues, so at SomeCondition(result, value)
value
can be not initiated.
You can try using Logical AND operator &
:
bool aBool = SomePredicate();
if (!aBool & !OutFunction(out int value))
{
return;
}
int result = -1; //other code here...
if (!aBool && SomeCondition(result, value))
{
}
bool SomePredicate() => false;
bool OutFunction(out int i) => false;
bool SomeCondition(int i, int j) => false;
So it always executes (Demo @sharplab.io). Or rewrite code in some other way (for example by declaring and initializing the variable before the OutFunction
call).
Compiler has some limitations of conditional flow and definite assignment analysis when it comes to such checks and it seems that this is one of the corner cases. Some of them were recently fixed for later compilers with C# 10 feature Improved Definite Assignment Analysis.
UPD
From the discussion @github.com/dotnet/csharplang several useful links were referenced, one of them stating the following:
To provide a little background, the compiler does what is usually referred to as a "path-independent flow analysis" for these situations. What this means practically is that conditional states are intersected at the end of the condition.
and
One way to learn about the states would be to do what's called a "path-dependent" flow analysis, but that can be significantly more expensive and is not in the design of C# 8.
So the simpler [mre] would be just:
using System;
bool aBool = SomePredicate();
int value;
if (!aBool)
{
value = 1;
}
if (!aBool)
{
Console.WriteLine(SomeCondition(value));// CS0165: Use of unassigned variable 'value'.
}
bool SomePredicate() => false;
bool SomeCondition(int i) => false;
@sharplab.io
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