只要我可以记得我避免使用开关声明不匹配.实际上,我不记得它曾经进入我的意识作为一种可能的方式来做事,因为它钻进了我的头在初期,这是没有什么比一个错误,在关的发言。然而,今天我遇到了一些代码,使用它的设计,这让我立即想知道什么每个人都在社区认为,关于开声明不匹配.

是不是一种编程语言应该明确不允许(C#不,虽然它提供一个解决方法),或者是它的一个特点的任何语言是足够强大,以留在程序员的手中?

编辑: 我不具体,足以什么我的意思是通过不匹配.我使用这类很多:

    switch(m_loadAnimSubCt){
        case 0: 
        case 1: 
            // Do something
            break;
        case 2:
        case 3:
        case 4:
            // Do something
            break;
   }

然而,我关切这样的事情。

   switch(m_loadAnimSubCt){
        case 0: 
        case 1: 
            // Do something but fall through to the other cases 
            // after doing it.
        case 2:
        case 3:
        case 4:
            // Do something else.
            break;
   }

这种方法,只要情况下为0、1它将尽一切在开关的发言。我已经看到了这个设计我只是不知道如果我同意那个开关的发言应该使用这种方式。我认为第一代的例子是一个非常有用和安全。第二,似乎种类的危险。

有帮助吗?

解决方案

这可能取决于您认为的漏洞。我很喜欢这种事情:

switch (value)
{
  case 0:
    result = ZERO_DIGIT;
    break;

  case 1:
  case 3:
  case 5:
  case 7:
  case 9:
     result = ODD_DIGIT;
     break;

  case 2:
  case 4:
  case 6:
  case 8:
     result = EVEN_DIGIT;
     break;
}

但是如果你有一个案例标签,后面跟着另一个案例标签的代码,我几乎总是认为这是邪恶的。也许将公共代码移动到一个函数并从两个地方调用将是一个更好的主意。

请注意,我使用 C ++ FAQ 定义isocpp.org/wiki/faq/big-picture#defn-evil“rel =”noreferrer“>”evil“

其他提示

这是一把双刃剑。有时非常有用,通常很危险。

什么时候好?当你想要10个案例时,所有处理方式都相同......

switch (c) {
  case 1:
  case 2:
            ... do some of the work ...
            /* FALLTHROUGH */
  case 17:
            ... do something ...
            break;
  case 5:
  case 43:
            ... do something else ...
            break;
}

我喜欢的一条规则是,如果你做任何想要排除休息的事情,你需要一个明确的评论/ * FALLTHROUGH * /来表明你的意图。

根据你正在做的事情,堕落真的很方便。考虑这种安排选项的简洁易懂的方法:

switch ($someoption) {
  case 'a':
  case 'b':
  case 'c':
    // do something
    break;
  case 'd':
  case 'e':
    // do something else
    break;
}

想象一下用if / else做这件事。这将是一团糟。

您是否听说过 Duff的设备?这是使用switch fallthrough的一个很好的例子。

这是一个可以使用的功能,它可以像几乎所有语言功能一样被滥用。

它可能非常有用几次,但一般来说,没有穿透是理想的行为。应该允许通过,但不是隐含的。

更新某些数据的旧版本的示例:

switch (version) {
    case 1:
        // update some stuff
    case 2:
        // update more stuff
    case 3:
        // update even more stuff
    case 4:
        // and so on
}

我喜欢在交换机中使用不同的回退语法,例如,errr ..

switch(myParam)
{
  case 0 or 1 or 2:
    // do something;
    break;
  case 3 or 4:
    // do something else;
    break;
}

注意:如果你使用标志声明你的枚举上的所有案例,那么枚举就已经可以了吗?听起来也不是那么糟糕,案件可能(应该?)很好地成为你的枚举的一部分。

对于使用扩展方法的流畅界面,这可能是一个很好的案例(没有双关语)?有点像错误...

int value = 10;
value.Switch()
  .Case(() => { /* do something; */ }, new {0, 1, 2})
  .Case(() => { /* do something else */ } new {3, 4})
  .Default(() => { /* do the default case; */ });

虽然这可能更不易读:P

如有任何东西:如果小心使用,它可以是一个优雅的工具。

然而,我认为存在的缺点多理由,不要使用它,并且最后不允许它了(C#)。其中的问题是:

  • 这很容易"忘记"的一个突破
  • 它并不总是显而易见的代码维护者这一省略是故意的突破

好好利用一下开关/不匹配的情况下:

switch (x)
{
case 1:
case 2:
case 3:
 do something
 break;
}

BAAAAAD使用的开关/不匹配的情况下:

switch (x)
{
case 1:
    some code
case 2:
    some more code
case 3:
    even more code
    break;
}

这可以改写,如果使用/其他结构没有损失在所有的在我的意见。

我的最后一句话:远离秋通过的情况下签如在不好的例子,除非你是维护传统代码在哪里这种风格是使用和理解。

强大而危险。堕落的最大问题是它不明确。例如,如果您遇到经常编辑的代码,其中有一个带有漏洞的开关,您如何知道这是故意的而不是错误?

我使用它的任何地方,我都确保它已正确评论:

switch($var) {
    case 'first':
        // fall-through
    case 'second':
        i++;
        break;
 }

在你的第一个例子中使用堕落显然是可以的,我不认为这是真正的堕落。

第二个例子是危险的(如果没有广泛评论)是不明显的。我教我的学生不要使用这样的结构,除非他们认为值得为它设一个评论块,这描述了这是一个故意的落实,以及为什么这个解决方案比替代方案更好。这样可以避免草率使用,但在使用它的情况下仍允许使用它。

这或多或少等同于我们在太空项目中所做的事情,当有人想要违反编码标准时:他们必须申请免除(我被要求就裁决提出建议)。

我不喜欢我的 switch 语句 - 它太容易出错并且难以阅读。唯一的例外是多个 case 语句都完全同样的事情。

如果有一些公共代码需要使用switch语句的多个分支,我将其提取到一个可以在任何分支中调用的单独的公共函数中。

在某些情况下,使用堕落是程序员的一种懒惰行为 - 他们可以使用一系列||例如,语句,而是使用一系列'全能'切换案例。

话虽如此,当我知道最终我仍然需要选项时(例如在菜单响应中),我发现它们特别有用,但还没有实施了所有选择。同样地,如果你正在为'a'和'A'做一个翻版,我发现使用切换掉落比使用复合if语句更清晰。

这可能是一种风格问题以及程序员的想法,但我并不喜欢以“安全”的名义删除某种语言的组成部分 - 这就是为什么我倾向于C及其变体/后代而不是比方说,Java。即使我没有“理由”,我也喜欢能够用指针等进行徘徊。到。

只有当它被用作跳转表到代码块时,才应该使用 think。如果代码的任何部分在更多情况下具有无条件中断,则所有案例组都应以此方式结束。其他任何事情都是“邪恶的”。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top