模式匹配变量范围

时间:2016-11-18 15:31:21

标签: c# pattern-matching c#-7.0

Roslyn Pattern Matching spec中声明:

  

模式变量的范围如下:

     

如果模式出现在if语句的条件下,则其范围   是if语句的条件和受控语句,但不是   其他条款。

然而,最新的微软“有什么新内容”postspresentations显示了这个例子:

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

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

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

2 个答案:

答案 0 :(得分:4)

从相同的文档:

  

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

实际上这段代码:

var Graph = React.createClass({

    render: function() {
        var ctx = document.getElementById("myChart");
        var myChart = new Chart(ctx, {
           type: 'bar',
           data: {
           labels: ["Red", "Blue", "Yellow"],
           datasets: [{
               label: '# of Likes',
               data: [12, 19, 3],
               backgroundColor: [
                  'rgba(255, 99, 132, 0.2)',
                  'rgba(54, 162, 235, 0.2)',
                  'rgba(255, 206, 86, 0.2)'
               ] 
            }]
          }
       });
    }
})

或多或少等于:

if (!(o is int i)) return; // type pattern "int i"

这意味着int i; if (!(SomeParsingOn(o, out i))) return; // type pattern "int i" i在同一级别上声明,这意味着它不仅适用于if,也适用于以下语句。当你复制if

时,这是真的
if

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

答案 1 :(得分:4)

我已将a similar question发布到Roslyn问题,并由 DavidArno 给出了答案:

  

很长,但你可以阅读为什么语言的所有血腥细节   设计团队选择"增强"这种语言在#12939

     

TL; DR你并不是唯一一个认为变化不直观的人   与范围以前的工作方式相矛盾。可悲的是,团队   虽然不在乎,但改变仍然存在。

似乎决定这个范围将适用,所以规范现在已经过时了,这个范围很遗憾:

  

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

     

这里的嵌入式语句的含义是用作的语句   另一个语句中的嵌套语句 - 除了块内。从而   if语句的分支,while,foreach等的主体。   将被视为嵌入式。

     

结果是变量总会逃脱   一个if,但从来没有它的分支。好像你把所有的卷曲都放在了   那些地方你应该"。

     

结论

     

虽然有点微妙,但我们会采用选项3.它会很好   平衡:

     

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