For some reason, M1()
causes a compiler error, while M2()
, which does the same thing, causes no error. Any idea why?
Using false ==
good find, here is what I think. note that this is definitely something that could be fixed, but I'm trying to find a reasoning for it. note that this is not accurate answer. just saying!
its not just false ==
that causes this problem, but also == true
causes i
to become unusable in either branch, so I went ahead and wrote this.
var x = obj is int i;
if(x) Console.WriteLine(i);
you get the same error. as you can see if x
is true then i
should be initialized, right? unless you start to muck with x
value! here x
is not constant therefor we can not guarantee that x
always remains true before executing if statement.
how ever compiler can compute constant values and expressions at compile time. I'm not sure what is happening here but what I think is
if((obj is int i) == false)
here ==
operator puts a gap between result of pattern matching and evaluating if statement, hence the error. I don't know why !
operator works fine, maybe they optimized that part but forgot to optimize this? ;)
I think this relates to Semantic Analysis phase of compiler, its job is to validate meaning of your code and determine how its executed, if there is something wrong, if there is possibility of undefined behavior or there is something totally meaningless, it fails and you get compile time error. read more about Phases of Compiler Design
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.