模式匹配变量范围

And*_*lon 11 c# pattern-matching c#-7.0

Roslyn模式匹配规范中,它指出:

模式变量的范围如下:

如果模式出现在if语句的条件中,则其作用域是if语句的条件和受控语句,而不是其else子句.

然而,最新的Microsoft"What's new" 帖子演示文稿显示了这个例子:

public void PrintStars(object o)
{
    if (o is null) return;     // constant pattern "null"
    if (!(o is int i)) return; // type pattern "int i"
    WriteLine(new string('*', i));
}
Run Code Online (Sandbox Code Playgroud)

其中显示了在模式匹配i的if级别范围之外使用的模式匹配变量.

这是一个疏忽,还是从规范中改变了范围?

Pat*_*man 6

来自同一个文档:

模式引入的变量——类似于前面描述的输出变量

所以实际上这段代码:

if (!(o is int i)) return; // type pattern "int i"
Run Code Online (Sandbox Code Playgroud)

或多或少等于:

int i;
if (!(SomeParsingOn(o, out i))) return; // type pattern "int i"
Run Code Online (Sandbox Code Playgroud)

这意味着i是在与 相同的级别上声明的if,这意味着它不仅在 范围内if,而且在以下语句的范围内。当您复制以下内容时,可以看出这是真的if

if (!(o is int i)) return; // type pattern "int i"
if (!(o is int i)) return; // type pattern "int i"
Run Code Online (Sandbox Code Playgroud)

给出错误 CS0128:名为“i”的局部变量已在此范围中定义

  • 嗯,是的,你是对的。这很尴尬。我希望他们能解决它。也许这只是一个错误,也许是正在进行中的工作。 (3认同)
  • 感谢您使用预览检查代码!这似乎与规范文档相矛盾,我将在 github 中搜索任何提及更改的内容。我个人不喜欢这种范围界定,因为它与定义变量(捕获和使用)的大多数其他语法不匹配。 (2认同)

And*_*lon 5

我发布了与罗斯林问题类似的问题DavidArno给出了答案:

很长,但是您可以在#12939中阅读有关语言设计团队选择以这种方式“增强”语言的所有详细信息。

TL; DR并非只有您一个人认为这种变化与示波器的工作方式不直观且矛盾。不幸的是,车队不在乎,变化将一直存在。

似乎已决定采用此范围,因此该规范现在已过时,可悲的是此范围仍然存在:

选项3:表达式变量的作用域是块,for,foreach和using语句,以及所有嵌入式语句:

嵌入式语句在这里的意思是,它被用作另一个语句中的嵌套语句-除了块内。因此,if语句的分支,while,foreach的主体等都将被视为嵌入的。

结果是变量将始终转义if的条件,但不会转义其分支。好像您在所有“应该放置”的地方都放置了卷发器一样。

结论

虽然有些微妙,但我们将采用选项3。它达到了很好的平衡:

它启用了关键方案,包括用于非Try方法的out var,以及在bouncer if语句中的模式和out var。它不会导致极端和违反直觉的多层次“溢出”。这确实意味着您将获得比当前限制性制度更多的范围变量。这似乎并不危险,因为确定的分配分析将防止未初始化的使用。但是,它阻止了变量名的重用,并导致更多名称显示在完成列表中。这似乎是一个合理的权衡。

  • 我一点也不喜欢这个。:( 这种方式更令人困惑。 (2认同)