Search code examples
c#.netcompiler-errors.net-4.0

Use of unassigned parameter compiler error, for a variable received from a function out parameter?


Today I encountered (by mistake) a weird compiler error and I don't understand the reason for it (compiler issue maybe?). .Net Framework 4.0 and Visual Studio 2019 if that matters.

The exact error is "Use of unassigned local variable 'value'" at the if after the TryParse. The code compiles fine if I use s or I cast d.s to string.

using System;
using System.Dynamic;

namespace TestConsoleApp
{
    static class Program
    {
        static void Main(string[] _)
        {
            string s = "1";

            dynamic d = new ExpandoObject();
            d.s = s;

            if (d.s != null && int.TryParse(d.s, out int value))
            {
                if (value == 1)
                {
                    Console.Out.WriteLine("OK!");
                }
            }
        }
    }
}

Solution

  • On the first sight it looks like a compiler bug. If you remove the d.s != null-check, which is unnecessary anyway, it will compile fine. But i think this comment here explains it: https://github.com/dotnet/roslyn/issues/39489#issuecomment-546003060


    Unfortunately, this is not a bug, this is caused by the existence of true/false operators in C#.

    You can define a type that would evaluate to true under left operand of && expression without evaluating the right operand of &&, something like this:

    class C {
      public static U operator==(C c, C d) => null;
      public static U operator!=(C c, C d) => null;
    }
    
    class U {
      public static U operator &(U c, U d) => null;
      public static implicit operator U(bool b) => null;
      public static bool operator true(U c) => true;
      public static bool operator false(U c) => false;
        
      public void M(C c, object o) {
        if (c != null && o is string s) {
          s.ToString(); // CS0165: Use of unassigned local variable 's'
        }
      }
    }
    

    When working with values of type dynamic, C# has no static information about the type and it's overloaded operators, so it assumes the "worse" - type like U in example above.