模式匹配和范围 - If 语句

Pattern matching and scope - If statements

所以,我一直在绞尽脑汁,或者更确切地说,我对以下代码片段缺乏思考:

public static void Main()
    {
        string a = "sdasd";
        object b = (object)a;
        object c = (object)a;
        
        if (b is string mystring) {
         Console.WriteLine(mystring);
        }
        if (c is string mystring) {
         Console.WriteLine(mystring);
        }
    }

(https://dotnetfiddle.net/tUTcOR)

尝试编译以上代码将产生编译时错误:

A local variable or function named 'mystring' is already defined or in this scope

我相信在 if 语句的表达式中声明的任何内容都在该语句的相同范围内,因此在上面的示例中 'main' 将定义范围。这是有道理的。


参考 MSDN 文档:

public static double ComputeAreaModernIs(object shape)
{
    if (shape is Square s)
        return s.Side * s.Side;
    else if (shape is Circle c)
        return c.Radius * c.Radius * Math.PI;
    else if (shape is Rectangle r)
        return r.Height * r.Length;
    // elided
    throw new ArgumentException(
        message: "shape is not a recognized shape",
        paramName: nameof(shape));
}

Let's examine both of those rules in detail, beginning with scope. The variable c is in scope only in the else branch of the first if statement. The variable s is in scope in the method ComputeAreaModernIs. That's because each branch of an if statement establishes a separate scope for variables. However, the if statement itself doesn't. That means variables declared in the if statement are in the same scope as the if statement (the method in this case.) This behavior isn't specific to pattern matching, but is the defined behavior for variable scopes and if and else statements.

The variables c and s are assigned when the respective if statements are true because of the definitely assigned when true mechanism.

(https://docs.microsoft.com/en-us/dotnet/csharp/pattern-matching)


鉴于上面的解释,我想特别注意两点,再提供一段代码:

That's because each branch of an if statement establishes a separate scope for variables

The variables c and s are assigned when the respective if statements are true

public static void Main()
{
    string a = "sdasd";
    object b = (object)a;
    object c = (object)a;
    
    if (b is string mystring) {
     Console.WriteLine(mystring);
    }else if (c is string mystringg)  {
     Console.WriteLine(mystringg);
    }else if (c is int mystringg) {
     Console.WriteLine(mystringg.ToString());
    }
        
}

(https://dotnetfiddle.net/FFZhyl)

因此,鉴于 c is string mystringgc is int mystringg 是在不同的范围内定义的(根据上面提到的第一条引述),并且两者都永远不会计算为 true(或者) 意味着只有两者之一会被初始化(根据上面的第二个引用),为什么上面的代码不能编译?

注意这个片段:

That's because each branch of an if statement establishes a separate scope for variables. However, the if statement itself doesn't.

That means variables declared in the if statement are in the same scope as the if statement (the method in this case.) This behavior isn't specific to pattern matching, but is the defined behavior for variable scopes and if and else statements.

这意味着 mystring 具有方法作用域。如果您测试 Sharplab.io 中的代码,您将看到此代码:

    string a = "sdasd";
    object b = (object)a;
    object c = (object)a;

    if (b is string mystring) {
       Console.WriteLine(mystring);
    }
    if (c is string mystring1) {
       Console.WriteLine(mystring1);
    }

翻译成这样:

    string text = "sdasd";
    object obj = text;
    object obj2 = text;
    string text2 = obj as string;
    if (text2 != null)
    {
        Console.WriteLine(text2);
    }
    string text3 = obj2 as string;
    if (text3 != null)
    {
        Console.WriteLine(text3);
    }