模式匹配 - 在 if 块之外的范围内的变量

Pattern matching - variable in scope outside if-block

我试图理解为什么 y 在以下示例的范围内:

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...
}

如果我将 int x 更改为 object x,则 y 不再在范围内(如预期的那样)。

为什么当被匹配的表达式是 int 类型时 y 在范围内,而不是当类型是 object 时?奇怪的是,作用域会根据表达式类型而变化。

当表达式类型和模式类型相同时,

y 似乎保留在范围内,并且它们都是 值类型 。 (当两种类型都是 DateTime 时存在同样的问题,但当它们都是 string 时不存在)。

(csc 版本为 2.0.0.61213。)


更新: 看起来 y 在两种情况下都在范围内。在 object 的情况下,编译器错误是 "Use of unassigned local variable 'y'." 所以它不会抱怨变量超出范围。

问题是创建的输出代码导致了这种奇怪的行为,在我看来这是一个错误。我想这最终会得到解决。

事情是这样的:x is int y 在编译时计算 true ,导致 if 过时并完成赋值在 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);

is object 变体的编译中似乎存在错误。它编译成这样的东西(注意我添加的括号):

int num = 1;
object arg;
bool flag = (arg = num as object) != null;

Console.WriteLine("This should NOT be in scope:" + arg);

这是有效的,即使在 C# 6 中也是如此。但是,编译器认为 arg 并不总是设置。添加 else 分支修复了这个错误:

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);

这是我在 VS15P4(或 P5)中发现的东西,并且在 GitHub 上被跟踪:

Definite assignment versus pattern-matching when pattern always matches #14651

抛开所有讨论,正如标题所暗示的,这是一个范围界定问题,当模式 always 匹配时会发生。

我以为它在 RC 之前就已经修复了,所以之后我没有实际测试过,但似乎问题仍然存在。

让我们看看它是否会在实际版本中修复,也就是明天:)