为什么“if”语句中的类型测试会泄露范围,而“switch”语句中的类型测试不会?[复制]

Why does type-testing in an "if" statement bleed scope, but type-testing in a "switch" statement does not? [duplicate]

提问人:user3163495 提问时间:7/29/2023 最后编辑:Rand Randomuser3163495 更新时间:7/29/2023 访问量:52

问:

在以下示例方法中,使用语句和语句进行类型测试。这些方法在功能上是相同的。但是,该语句不允许在强制转换时重复使用相同的变量名。object oswitchififxobject o

为什么声明允许这样做,但声明不允许?switchif

public sealed class Test
{
    public long GetLengthA(object o)
    {
        switch (o)
        {
            case Stream x:
                {
                    return x.Length;
                }
            case Array x: // <-- this is allowed
                {
                    return x.Length;
                }
        }
        return 0;
    }
    public long GetLengthB(object o)
    {
        if (o is Stream x)
        {
            return x.Length;
        }
        else if (o is Array x) // <-- this is NOT allowed
        {
            return x.Length;
        }
        return 0;
    }
}

错误 CS0136:无法在此声明名为“x”的本地或参数 作用域,因为该名称在封闭的本地作用域中用于定义 本地或参数

enter image description here

C# 类型 强制转换 switch-statement

评论

2赞 Rand Random 7/29/2023
这有帮助吗?github.com/dotnet/csharplang/blob/main/proposals/csharp-7.0/......
1赞 7/29/2023
一言以蔽之:范围。在您提供的代码中,允许在 switch 语句中声明相同变量的原因是“x”位于 switch 语句内的不同大小写块中。每个“case”块都为模式匹配变量创建一个新范围。“if”语句并非如此。您尝试创建的变量使用的是“方法作用域”或外部作用域。

答:

1赞 Harsh Shah 7/29/2023 #1

基本上在 switch-case 中,每个情况都被视为它自己的作用域/块,因此您可以重用变量名称,但使用 if-else 梯形图,整个函数都是作用域/块,因此您不能真正重用该名称。尝试将第二个变量 x 更改为 y 或其他变量。

请看这里,https://dotnetfiddle.net/LFyxXS

1赞 PMF 7/29/2023 #2

这基本上是因为在 if 语句中定义的变量的作用域确实超出了 if 测试的范围。

此代码有效(但见下文):

    public long GetLengthB(object o)
    {
        if (o is Stream x)
        {
            return x.Length;
        }
        
        return x.Length * 2;
    }

x在作用域结束后有效,但是不能这样使用,因为编译器会抱怨它是未定义的,因为在条件为 false 的情况下它不会初始化。乍一听这可能很傻,但如果你反转条件,它现在就有意义了:

    public long GetLengthB(object o)
    {
        if (!(o is Stream x))
        {
            throw new NotSupportedException(...);
        }
        
        return x.Length;
    }