问题
I'm trying to understand why y
is in scope in the following example:
static void Main(string[] args)
{
int x = 1;
if (x is int y) { }
Console.WriteLine("This should NOT be in scope:" + y); // but it is...
}
If I change int x
to object x
, then y
is no longer in scope (as expected).
Why is y
in scope when the expression being matched is of int
type and not when the type is object
? It's odd that the scoping changes based on the expression type.
y
seems to stay in scope when the expression type and the pattern type are the same, and they're both value types. (Same issue exists when both types are DateTime
, but doesn't exist when they're both string
).
(csc version is 2.0.0.61213.)
Update: It looks like y
is in scope in both cases. In the object
case, the compiler error is "Use of unassigned local variable 'y'." So it's not complaining about the variable being out of scope.
回答1:
The problem is the output code created, which results in this strange behavior, which is a bug in my opinion. I guess this will be fixed eventually.
The thing is this: x is int y
evaluates to true
on compile time, resulting in the if
rendered obsolete and the assignment done before the if
. See the compiled code here:
int num = 1;
int num2 = num;
bool flag = true;
if (flag)
{
}
Console.WriteLine("This should NOT be in scope:" + num2);
There seems a bug in the compilation of the is object
variant. It compiles to something like this (note the parenthesis I added):
int num = 1;
object arg;
bool flag = (arg = num as object) != null;
Console.WriteLine("This should NOT be in scope:" + arg);
Which is valid, even in C# 6. However, the compiler thinks arg
isn't always set. Adding an else
branch fixes this bug:
else { y = null; }
Results in:
int num = 1;
object arg;
bool flag = arg = num as object != null;
if (!flag)
{
arg = null;
}
Console.WriteLine("This should NOT be in scope:" + arg);
回答2:
That's is something I had found in VS15P4 (or P5) and it was being tracked on GitHub:
Definite assignment versus pattern-matching when pattern always matches #14651
Putting aside all the discussions, it is a scoping issue which occurs when the pattern always matches, as the title suggests.
I thought it was fixed before RC so I haven't actually tested afterwards but it seems the issue still persists.
Let's see if it will be fixed in the actual release, which is tomorrow :)
来源:https://stackoverflow.com/questions/42483485/pattern-matching-variable-in-scope-outside-if-block