【问题标题】:What is the difference and why does Switch Case work like this in C#? [duplicate]有什么区别,为什么 Switch Case 在 C# 中这样工作? [复制]
【发布时间】:2018-07-23 08:57:52
【问题描述】:

我有两个函数,一个可以编译,一个不能。有什么区别?

函数号 1 是否假定案例 1 总是会被命中,或者它只是一个编译器问题?

public void Test(int x)
{
    switch (x)
    {
        case 1:
            uint cId = (uint)3;
            break;

        case 2:
            cId = (uint)5; //NO ERROR HERE. WHY?
            break;
    }
}

public void DeclaringInsideSwitch(int x)
{
    uint tst = 0;
    switch (x)
    {
        case 1:
            int y = 3;
            uint variable = tst;
            break;

        case 2:
            variable++; //ERROR HERE. WHY?
            break;
    }
}

我当然尝试搜索“在 C# 中的 switch case 中声明变量”,但对我来说,现在这似乎是 C# 中的某种错误,为了向后兼容而保留。

// 在收到已回答的警告后,我的问题现在可以简化为真正的问题。

为什么:

int x;
x++;

这不行吗?

【问题讨论】:

  • 所以不同之处在于您只是在第一个代码中为变量赋值,但在第二个代码中您实际上尝试使用它(由于尚未初始化而失败)
  • variable++ 首先读取变量,然后写入一个比读取到的变量大一的新值。但是对于局部变量(即在方法/访问器/等中声明的变量),如果编译器无法证明该变量已被设置,则不允许您读取。在您的最后一个示例中,这是允许的:case 2: variable = 100; variable++; break;
  • 我的问题非常接近“C# switch 语句中的变量声明”,但是你应该看到那个变量++,甚至编译失败!这让我很困惑
  • 您是否阅读了错误信息?这应该会给你一个大量线索出了什么问题。
  • 作为解决此类问题的一般答案:不断缩小两段代码之间的差异,直到达到无法再更改任何内容而不破坏不同行为的地步。在这种情况下,您会发现分配给本地人与从本地人读取不同。除非您已经知道编译器如何翻译两个完整的代码块,否则您的两个示例差异太大,无法得出任何结论。我们要求重现问题的最短代码是有原因的 :)

标签: c# .net switch-statement


【解决方案1】:

基本上,变量声明实际上比您想象的要宽;第二个示例存在“​​明确赋值”问题,因为它被声明(更宽),但并未实际赋值,因此++ 对未赋值的值毫无意义。

如果您想要每个case 的范围,您可以这样做...只需添加大括号:

        switch (x)
        {
            case 1:
            {
                uint cId = (uint)3;
                break;
            }
            case 2:
            {
                uint cId = (uint)5;
                break;
            }
        }

是不是有点烦?是的。是反直觉的吗?是的。它会被改变吗?不太可能,因为这将是一个重大的突破性更改,会阻止许多现有的 C# 编译。

【讨论】:

  • @KonradRudolph 是的,是的,我愿意
  • @DanielOfTaebl:不是 Marc,而是考虑 how one developer just broke Node, Babel and thousands of projects in 11 lines of JavaScript 的(非 C#)情况。如果您更改依赖项,所有 的消费者将不得不处理更改行为。如果您更改代码的编译方式,所有 消费者(即编译 C# 的每个人)都会受到影响。让一个应用程序可以工作,没有被触及,但现在不知何故无法工作是非常不直观的,并导致大量的调试工作(什么失败了?为什么?发生了什么变化?...)
  • @KonradRudolph - 考虑到程序员的一般素质,我认为包含switch 的程序数量,程序员最初试图在多个cases 中声明相同的变量,得到一个“重复声明”错误并通过删除除一个声明之外的所有声明来清除此错误将大大高于他们真正理解问题并将声明完全移出@987654327的相同情况@(或为每个 case 引入单独的范围)。
  • @KonradRudolph,C# 语言设计/编译器团队大量关注反向兼容;如果该警告可以在现有代码上触发(因为可以启用warn-as-error等),他们有一个非常高的标准只是添加一个新警告 - 默认响应将是“添加它而是通过分析仪”;我认为出售这种变化的机会逐渐接近于零。
  • @Daniel “你愿意用一个荒谬的微小突破性变化的故事来取悦我们吗......”这是一个错误的问题。没有人实现功能,因为“嘿,几乎没有负面后果”。正如 Raymond Chen 常说的那样:每个功能都以 -100 分开始,您必须展示为什么该功能值得付出巨大努力。那么,您能否展示当前行为导致严重错误的单个专业程序(即不是学生作业)?我觉得很难想象。
【解决方案2】:

好吧,uint cId 是在 {...} 内定义的 范围 在你的情况下是 switch scope

switch (x)
{
    case 1:
        uint cId = (uint)3; // <- definition 
        break;

    case 2:
        // cId has been defined and thus can be assigned (initialization)
        cId = (uint)5; //NO ERROR HERE WHY?
        break;
}  // <- end of cId scope

在第二种情况下variable被定义,但作为一个局部变量必须在使用前初始化(增量):

switch (x)
{
    case 1:
        int y = 3;
        uint variable = tst; // <- definition 
        break;
    case 2:
        // variable defined, but has not been initialized ("case 1:" hasn't been run),
        // variable contains trash and so you can't increment it 
        variable++; //ERROR HERE WHY?
        break;
} // <- end of variable scope

【讨论】:

  • 现在,我明白了。我有 ++ 的编译错误,因为变量未初始化。当进行分配时,它不是编译错误。谢谢
  • 只是为未来的人添加一点,将variable++ 视为variable = variable + 1 可能会有所帮助,并且由于variable 未定义,因此您会遇到异常
猜你喜欢
  • 2011-11-09
  • 2021-07-18
  • 1970-01-01
  • 2013-07-14
  • 1970-01-01
  • 2018-03-23
  • 2013-02-19
  • 2012-01-20
相关资源
最近更新 更多