【问题标题】:Pattern matching and scope - If statements模式匹配和范围 - If 语句
【发布时间】:2020-04-06 17:50:29
【问题描述】:

所以,我一直在为以下 sn-p 代码绞尽脑汁,或者说是缺乏大脑:

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)

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

一个名为“mystring”的局部变量或函数已被定义或在此范围内

我被引导相信在 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));
}

让我们从范围开始详细检查这两个规则。变量 c 仅在第一个 if 语句的 else 分支的范围内。变量 s 在方法 ComputeAreaModernIs 的范围内。这是因为 if 语句的每个分支都为变量建立了一个单独的范围。但是,if 语句本身没有。这意味着 if 语句中声明的变量与 if 语句(本例中的方法)在同一范围内。此行为不是特定于模式匹配,而是变量范围以及 if 和 else 语句的定义行为。

变量 c 和 s 在各自的 if 语句为真时被赋值,因为当真时明确赋值的机制。

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


现在有了上面的解释,我想注意两个具体点,并提供另一个代码sn-p:

这是因为 if 语句的每个分支都为变量建立了单独的范围

当各自的 if 语句为真时,变量 c 和 s 被赋值

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(或者),这意味着两者中只有一个会曾经被初始化(根据上面的第二个引用),为什么上面的代码不能编译?

【问题讨论】:

  • 您尚未在括号内输入新范围。例如,您可以以同样的方式将 out 变量声明为 TryParse 的一部分。在第一个if 语句之后尝试访问myString
  • “在 if 语句中声明的变量与 if 语句在同一范围内”对我来说似乎很清楚
  • 您引用的文档准确地解释了为什么会发生这种情况。 c 被重新限定范围,因为它只能作为 if 语句的分支使用。

标签: c# c#-7.0 c#-8.0


【解决方案1】:

注意这个片段:

这是因为 if 语句的每个分支都为变量建立了一个单独的范围。 但是,if 语句本身没有。

这意味着 if 语句中声明的变量与 if 语句(本例中的方法)在同一范围内。此行为不是特定于模式匹配,而是变量范围以及 if 和 else 的定义行为声明。

这意味着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);
    }

【讨论】:

  • 啊,有道理。不知道为什么我没有反编译单个模式匹配表达式,并查看输出。谢谢。
猜你喜欢
  • 2014-07-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多