C#7.0模式匹配变量的范围和赋值语法

问题描述 投票:0回答:2

Pre:Pattern match variable scope,但我想更多地了解分配行为。

我做了以下测试。

在F1中,似乎i在范围内但未分配,我可以通过F2理解它。

但F3的情况让我感到很困惑,因为F2无法解释。

然后在F4中它显示!在这种情况下没有影响。

// inside a class
object o = 1;
void F0() { // normal usage
    if(o is int i)
        WriteLine(i);
}
void F1() {
    if (o is int i)
        WriteLine(i);
    else
        WriteLine(i); // Use of unassigned local variable 'i'
    WriteLine(i); // the same as above
}
void F2() {
    int i;
    if (o is int) {
        i = (int)o; // just for simulation because 'as' can't unbox
        WriteLine(i);
    }
    else
        WriteLine(i); // Use of unassigned local variable 'i'
    WriteLine(i); // Use of unassigned local variable 'i'
}
void F3() {
    if (!(o is int i))
        WriteLine(i); // Use of unassigned local variable 'i'
    else
        WriteLine(i); // compile
    WriteLine(i); // Use of unassigned local variable 'i'
}
void F4() {
    _ = !(o is int i);
    Console.WriteLine(i); // Use of unassigned local variable 'i'

    _ = o is int i;
    Console.WriteLine(i); // Use of unassigned local variable 'i'
}

我只能得出结论,这个语法对if的处理方式不同,如果if condition为真,它将在if true的范围内分配,否则它将在if else的范围内分配。

我的理解是否正确?(我猜不是

c# c#-7.0
2个回答
0
投票

让我们仔细看下面的声明:

o is int i

如果o可以转换为int类型,则此语句将返回true并将设置i变量。如果没有,它将返回false并且i变量将不会被初始化。此外,在if语句中使用此类代码会将变量移动到外部作用域。

让我们来看看你的方法:

void F1() {
   if (o is int i)
        WriteLine(i);  // i was initialized, because o is int i returned true
    else
        WriteLine(i); // i was NOT initialized, so you have using of unassigned local variable 'i' here
    WriteLine(i); // the same as above, because i wasn't initialized in all code paths before this statement
}

void F2() {
    int i;
    if (o is int) {
        i = (int)o; // just for simulation because 'as' can't unbox
        WriteLine(i); // i was initialized in previous line
    }
    else
        WriteLine(i); // o is not int, so i wasn't initialized => using of unassigned local variable 'i'
    WriteLine(i); // i wasn't initialized in all code paths, using of unassigned local variable 'i'
}

void F3() {
    if (!(o is int i))
        WriteLine(i); // Using of unassigned local variable 'i' because o can't be casted to int => !(o is int i)
    else
        WriteLine(i); // compile - i was initialized
    WriteLine(i); // you wrote this statement can be compiled, in fact not, because i is not initialized in all code paths
}

void F4() {
    _ = (!(o is int i));
     Console.WriteLine(i); // Use of unassigned local variable 'i', because in case of unsuccessful casting i won't be intialized.
}

1
投票

来自spec for patterns in C# 7.0

Scope of pattern variables

在模式中声明的变量的范围如下:

  • 如果模式是案例标签,则变量的范围是案例块。

否则,变量在is_pattern表达式中声明,其作用域基于紧接着包含is_pattern表达式的表达式的构造,如下所示:

  • 如果表达式位于表达式的lambda中,则其范围是lambda的主体。
  • 如果表达式位于表达式身体方法或属性中,则其范围是方法或属性的主体。
  • 如果表达式在when子句的catch子句中,则其范围是catch子句。
  • 如果表达式在iteration_statement中,则其范围就是该语句。
  • 否则,如果表达式是某种其他语句形式,则其作用域是包含该语句的作用域。

为了确定范围,embedded_statement被认为是在其自己的范围内。例如,if_statement的语法是

if_statement
    : 'if' '(' boolean_expression ')' embedded_statement
    | 'if' '(' boolean_expression ')' embedded_statement 'else' embedded_statement
    ;

因此,如果if_statement的受控语句声明了一个模式变量,则其范围仅限于embedded_statement:

if (x) M(y is var z);

在这种情况下,z的范围是嵌入式语句M(y is var z);

其他情况是由于其他原因的错误(例如,在参数的默认值或属性中,这两个都是错误,因为这些上下文需要常量表达式)。

在C#7.3中,我们添加了以下可以声明模式变量的上下文: - 如果表达式在构造函数初始值设定项中,则其作用域是构造函数初始值设定项和构造函数体。 - 如果表达式在字段初始值设定项中,则其范围是出现的equals_value_clause。 - 如果表达式位于指定要转换为lambda主体的查询子句中,则其范围就是该表达式。

© www.soinside.com 2019 - 2024. All rights reserved.