`out` variable unassigned... unless the condition is inline?

Viewed 248

I'm trying to understand what the C# compiler's rules are for deciding when an out variable was assigned.

Here's one example that baffles me. Let's assume we have a Dictionary<>:

var dict = new Dictionary<string, string>();

Let's start with a simple condition: this compiles.

var found = dict.TryGetValue("b", out var val);
if(found)
{
    Console.WriteLine(val); //no problem
}

If the condition is slightly more complicated, it's a compile error:

var aBool = true;
var found = aBool && dict.TryGetValue("b", out var val);
if(found)
{
    Console.WriteLine(val); //use of unassigned local variable val
}

OK, so I guess the compiler doesn't deal with logical operators in this case.
...but if we move the exact same condition inline, it's all rainbows again:

var aBool = true;
if(aBool && dict.TryGetValue("b", out var val))
{
    Console.WriteLine(val); //compiles fine
}

Why?

1 Answers

The compiler cannot guarantee that the variable val is initialized. In that context, aBool is some non-constant boolean expression. Depending on the value of aBool, val may or may not be initialized since the expression may not be evaluated due to the short circuiting &&.

To help the compiler out, you would have to make aBool constant so the compiler can then perform the full analysis. If aBool == true, val is definitely initialized. If false, val is definitely not initialized. Flow analysis could then determine that found will be set to a value consistent with the state of the val variable.

const bool aBool = true;
...

The reason why the second case is fine, val is only ever used in the body of the if statement. And the body will only be entered if both aBool is true and the TryGetValue() call succeeds (and consequently val is initialized).

Related