【问题标题】:Differences between switch statements in C# and C++C# 和 C++ 中 switch 语句的区别
【发布时间】:2012-10-25 17:59:19
【问题描述】:

我刚开始自学 C#,在关于 Switch 语句的教程中,我读到:

执行流程被禁止流动的行为 从一个案例块到下一个案例块是 C# 不同的一个领域 C++。在 C++ 中,case 语句的处理允许从 一对一。

为什么它在 C# 中的一个 case 语句之后停止?如果您可以使用break 语句在任何时候停止,那么在 C# 与 C++ 中是否有任何理由在找到匹配项后让它停止?如果你想在 C# 中使用多个 case,是否必须使用另一个 Switch 语句?

【问题讨论】:

  • 我想它平衡了您可以使用字符串这一事实。
  • 禁止掉线让 C# 不那么“混乱”
  • @Greg,虽然我必须说我以前可能使用过一次失败。如果它没有失败,为什么首先需要休息呢?
  • 它惹恼了来自 C 的人......顺便说一句,他们为什么不完全删除 break 关键字,而他们正在使用它?
  • @SamIam:只要案例主体为空,C# 就允许失败。

标签: c# c++ switch-statement


【解决方案1】:

这可能完全属于反模式领域,但如果你真的想要失败行为,这可能应该接近与跳转表相同

using System;

namespace MyApplication
{
  class Program
  {
    static void Main(string[] args)
    {
      int day = 4;
      switch (day) {
        case 1: goto d1;
        case 2: goto d2;
        case 3: goto d3;
        case 4: goto d4;
        case 5: goto d5;
        case 6: goto d6;
        case 7: goto d7;
      }    
      d1: Console.WriteLine("Monday");
      d2: Console.WriteLine("Tuesday");
      d3: Console.WriteLine("Wednesday");
      d4: Console.WriteLine("Thursday");
      d5: Console.WriteLine("Friday");
      d6: Console.WriteLine("Saturday");
      d7: Console.WriteLine("Sunday");
    }
  }
}

【讨论】:

    【解决方案2】:

    从技术上讲,这是不正确的:当 case 的主体为空时,C# 确实允许失败:

    switch(val) {
    case 1:
    case 2:
        Console.WriteLine("small");
        break;
    case 3:
    case 4:
    case 5:
    case 6:
    case 7:
        Console.WriteLine("medium");
        break;
    
     default:
        Console.WriteLine("large");
        break;
    }
    

    在 C/C++ 中的非空主体之后允许隐式失败通常是错误的。这就是 C# 的设计者决定不允许它使用的原因。

    【讨论】:

    • 我一直不明白的是......如果不允许掉线,为什么我们必须明确添加break
    • @Servy: ಠ_ಠ 认真的吗?为什么正确使用 switch 会是一件坏事?
    • @LightStriker 嗯,这主要是个玩笑,但确实有一定道理。这个想法是,虽然有时是适当的,但经常被误用。让它更难使用意味着它更有可能只在真正合适的时候使用。
    • @LightStriker “切换用户”和“不切换用户”之间存在着长期的圣战。不要卷入其中,以免它的愤怒永远吞噬你的灵魂。
    • 当然,上面的代码在 C# 中是合法的,但是你是否将其命名为“fall-through”,取决于术语。根据 C# Spec 中使用的术语,上述switch 语句由三个switch 部分 组成。第一个部分有两个开关标签,第二个部分有五个标签,第三个也是最后一个部分有一个标签。大括号{ ... } 内的整个区域称为switch 块。使用这个术语,从 section 到下一个 section 是绝对不允许的。来源:C# Spec
    【解决方案3】:

    C# 的版本更不容易出错 - 如果您忘记写 break,什么都不会在您的脸上爆炸,这种情况发生了。它看起来也更好一些。话又说回来,无论如何,在大多数情况下都没有什么理由使用 switch 语句(通常它最终只是一个糟糕的类型分派实现,它通过类继承在两种语言中都内置)。

    【讨论】:

    • 我同意switch 真正有用的情况并不多。它是一长串 if/else 语句的更简洁版本,并且与一长串 if/else 语句一样存在缺陷。
    【解决方案4】:

    我认为争论的焦点是 C++ 中的 switch 语句通常导致的问题多于解决的问题。 IE。当他们在不是程序员意图的情况下失败时,他们只是忘记了break。所以 C# 取消了它。

    与 C++ 中的许多其他“功能”相同。并不是说它们偶尔没有用,只是更多时候它们是有害的。就像将任何东西评估为布尔值一样,所以在 C# 中你不能这样做:

    if(1) 
    {
    
    }
    

    因为将整数评估为布尔值会导致很多难以发现的错误。

    【讨论】:

    • 这个“特性”也惹恼了 C 程序员。他们至少可以让非空引用评估为真。
    • @AlexandreC.:我认为主要问题是混淆了===。如果一个非空引用被评估为真,那么if (myFoo=myBar)when 在 C++ 中将被评估为真,但它会导致 C# 中的编译器错误。恕我直言,这不是一件坏事。
    • @AlexandreC。如果你有一个可以为空的布尔值,那可能会导致各种混乱。
    • @Servy:可以为空的布尔值在if 语句中是否被正确提升?
    • @AlexandreC。不,这就是我的观点。 (目前您需要将其转换为不可为空的布尔值。)您的建议会导致这种情况发生,这会导致混淆和模棱两可,或者与引用类型的行为不一致,也会导致混淆和抱怨。我不是说你不能让它以某种方式工作,我只是说无论你做什么,它都会......混乱和一大群人会感到困惑。
    【解决方案5】:

    C# 具有goto case,它具有fallthrough 的所有好处,但更难意外实现。

    Example on MSDN

    【讨论】:

    • 你会看那个。这很漂亮。
    • 等等,switch 不是添加到 C++ 中以摆脱 C 的 goto 意大利面条吗?
    • @Gregory:不,C 也有switch(因为 waaaaay 回来了,它本来是一个跳转表的源代码版本)
    • 也许故事是它被添加到 C 来修复基本的;但我似乎记得将switch 包含在语言中以“修复”goto 代码创建的所有问题背后存在某种争议。我得试试看能不能找到我想要的参考资料……
    • @Gregory: switch 绝对不是 C gotoif 的演变。它可以被认为是 C 等价于 BASIC "computed goto",C 的 goto 根本不支持,并且更接近 C 函数指针。
    猜你喜欢
    • 2012-10-01
    • 2011-11-27
    • 1970-01-01
    • 2015-01-08
    • 2017-12-13
    • 1970-01-01
    • 1970-01-01
    • 2021-07-24
    • 2016-07-12
    相关资源
    最近更新 更多