Search code examples
c#compiler-errorsnullableoutnull-propagation-operator

Use of unassigned local variable error is incorrectly indicated by compiler


Given this code:

private void TryIt(Dictionary<int, int> myDict)
{
    if (myDict?.TryGetValue(1, out int myValue) ?? false)
    {
        Console.Out.WriteLine(myValue); // <-- Error CS0165
    }
}

The c# compiler emits:

error CS0165: Use of unassigned local variable 'myValue'

But it is clearly not possible to reference myValue when the call to TryGetValue() is skipped by the ?. operator. This is because the resulting null is converted to false by ?? false.

In other words, if myDict is null, the ?. operator will skip the call to TryGetValue(), leaving myValue unassigned. I get that.

BUT the ?? operator will then always evaluate that null propagation to false, preventing entry into the if-block in this case.

This is evident at compile-time, so why the error?

I suspect that it probably has to do with how all this syntactic sugar is eventually unwound into actual .NET p-code, but it still seems wrong to error out...

When not using the .? operator, I get no error, which is expected:

    if (myDict.TryGetValue(1, out int myValue))
    {
        Console.Out.WriteLine(myValue); // <-- NO ERROR
    }

It's just when I use .? with ?? false.


Solution

  • "But it is clearly not possible ..."

    That is correct but the compiler does not track the logic that deeply.

    The compiler could have deduced this, but note that the scope of myValue extends beyond the if statement:

    if (myDict?.TryGetValue(1, out int myValue) ?? false)
    {
        Console.Out.WriteLine(myValue); // <-- Error CS0165
    }
    Console.Out.WriteLine(myValue); // myValue is in scope here
    

    So while you might desire that the compiler figured out all the ?. and ?? logic, and that the code inside the if () { ... } is a special case, that apparently is a feature that wasn't deemed important enough.

    myDict?.TryGetValue(1, out int myValue) does not always assign to myValue.