Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# 7 Compiler Error - Pattern Matching

Tags:

c#

c#-7.0

For some reason, M1() causes a compiler error, while M2(), which does the same thing, causes no error. Any idea why?

Using false == should be the same as using the not operator, !.

Use of unassigned local variable 'i'

class Program {
    static void Main(string[] args) {
        int x = 8;

        M1(x);
        M2(x);
    }  // Main()

    public static void M1(Object obj) {
        if (false == (obj is int i))  // Causes ERROR on WriteLine
            return;

        System.Console.WriteLine(i); // Use of unassigned local variable 'i'
    }

    public static void M2(Object obj) {
        if (!(obj is int i))  // OKAY
            return;

        System.Console.WriteLine(i);
    }
} // class Program
like image 820
Tom Baxter Avatar asked Nov 11 '17 19:11

Tom Baxter


1 Answers

The issue here is with the way the compiler handles "definitely assigned when true". ! inverts that; == false doesn't. So for the code:

if (!(obj is int i))
        return;

System.Console.WriteLine(i);

The compiler can infer that if obj is int i is false, the ! inverts that, thus return will occur if it's not an int. Therefore i can be allowed to "leak" into subsequent code safely.

However, the same rules do not apply to == false. Whilst semantically identical to a human reader of the code, the compiler treats ! and == false as very different things. So for:

if (false == (obj is int i))

the compiler baulks and takes the view it cannot know the assignment state of i, thus the error.

For a discussion on this, please see Incorrect "Use of unassigned local variable" for (x is T y) == false.

The moral of the story: avoid comparing to false and use ! when using C# patterns.

EDIT

It should be noted that == false is not a special case here. Any use of == removes the ability of the compiler to determine "definitely assigned when true". For example, the following code compiles:

object x = 1;
if (!(x is bool y))
    return 0;

var z = y;

But add a == true and it no longer does:

object x = 1;
if (!(x is bool y == true))
    return 0;

var z = y; // error: use of an unassigned variable

EDIT2

Incidently, for anyone who uses if (expression == false) because they find if (!expression) difficult to read, you may be interested to know that the syntax, if !(expression) is being considered for C# 8.

like image 184
David Arno Avatar answered Oct 02 '22 12:10

David Arno