何时使用'if ... else if'以及何时使用

时间:2010-09-02 19:25:27

标签: c# coding-style

1)我知道if…else if语句是如何工作的,但在下一个例子中,就结果值而言,两种方法都是相同的。那么我使用的两种方法中的哪一种或者我应该总是选择一种在语义上最接近代码尝试的方法(这里我猜这两种方法在语义上是完全不同的)?那么你会使用哪种方法?为什么?

protected string GetNumberDescription(int value)
{
    if (value >= veryBigNumber)
        return veryBigNumberDescription;
    else if (value >= bigNumber)
        return bigNumberDescription;
    else if (value >= smallNumber)
        return smallNumberDescription;
    else
        return "";
}

protected string GetNumberDescription(int value)
{
    if (value >= veryBigNumber)
        return veryBigNumberDescription;
    if (value >= bigNumber)
        return bigNumberDescription;
    if (value >= smallNumber)
        return smallNumberDescription;
    else
        return "";
}

2)我注意到在编写if ... else if语句时,代码丢失使用了以下格式:

if ...
else if ...
else ...

但不是(至少在概念上)更正确的方式:

if ...
else
  if ...
  else ...

18 个答案:

答案 0 :(得分:16)

  1. 您应该使用第一个。它更受欢迎,也更符合逻辑。 (如果这个条件成立,你不关心任何事情......在你的代码中注明。)
  2. 使用第一种方式(否则如果)通常更容易接受,更紧凑和可读。 Python甚至还有一个特定的关键字(elif)。

答案 1 :(得分:13)

我个人会使用

protected string GetNumberDescription(int value)
   {
       if (value >= veryBigNumber)
           return veryBigNumberDescription;
       if (value >= bigNumber)
           return bigNumberDescription;
       if (value >= smallNumber)
           return smallNumberDescription;
       return string.Empty;
   }

这完全取决于你的功能在做什么。如果它像这样简单,那么保持简单。如果您在返回之前可能需要对结果执行某些操作,那么我将使用Egrunin的解决方案

答案 2 :(得分:12)

protected string GetNumberDescription(int value) 
{ 
    string ret = "";

    if (value >= veryBigNumber) 
        ret = veryBigNumberDescription; 
    else if (value >= bigNumber) 
        ret = bigNumberDescription; 
    else if (value >= smallNumber) 
        ret =  smallNumberDescription; 

    return ret; 
} 

这个问题已经回答了,但我补充说是因为:

  1. 从函数中单个退出是有好处的。
  2. 重复测试相同的变量,因此if / elseif最合适。
  3. 已编辑添加:

    在这种情况下,我通常很早就退出了一个函数:

    if (conditionOne)
    {
        if (conditionTwo)
        {
            if (conditionThree)
            {
                interesting_stuff();
            }
        }
        else
            boring();
    }
    return;
    

    我很高兴看到这个:

    if (!conditionOne)
        return;
    
    if (!conditionTwo)
    {
        boring();
        return;
    }
    
    if (!conditionThree)
        return;
    
    interesting_stuff();
    return;
    

    但是当有许多不同的嵌套级别退出时,当您阅读代码时,很容易错过一个。

    另外,正如评论中所提到的:单个退出意味着只有一个地方可以设置断点。

答案 3 :(得分:11)

如果条件是相互排斥的,那么我认为如果模式是最好的话。随着代码的发展和变得更加复杂,意外破坏将更加困难,因为您的控制流更准确地代表了逻辑的相互排斥性。

考虑是否有人重新考虑你的第一个例子与egrunin的例子类似,只有一个返回,但是考虑他们忘记在每个例句中添加“else”:

protected string GetNumberDescription(int value) 
{ 
    string ret = "";

    if (value >= veryBigNumber) 
        ret = veryBigNumberDescription; 
    if (value >= bigNumber) 
        ret = bigNumberDescription; 
    if (value >= smallNumber) 
        ret =  smallNumberDescription; 
    // BUG: very big numbers still fall through to this last condition, 
    //         because they meet all conditions

    return ret; 
} 

他们刚刚介绍了一个错误。他们可能没有意识到回报是所表达的逻辑的一部分。虽然这里的错误是显而易见的,但在现实生活中,这段代码在未来几年内可能会变得更复杂,更冗长,更难以阅读,从而更容易犯这样的错误。

检测到意外错误

另外,如果必须满足至少一个条件(即永远不应该返回一个空字符串),那么如果你假设所有的情况都应该被处理,那么我会在最后的其他情况下抛出异常。这将检测代码中的错误,其中代码通过所有省略并且没有找到匹配条件。如果您不抛出异常,那么该错误可能会导致奇怪的行为。其余代码如何处理未初始化的空字符串?主要取决于手头的代码。抛出异常的想法是在错误发生的地方造成严重的故障,以便可以轻松识别和纠正错误,而不是让应用程序继续以无效的返回运行。

if (value >= smallNumber) 
    ret =  smallNumberDescription; 
else if(...)
    ret =  otherNumberDescription; 
else
    throw new InvalidOperationException($"No condition matched for value={value}");

return ret; 

如果与适当的异常日志记录/通知配对,那么这将允许您了解此错误并添加条件来处理意外的值。对于非常简单的条件来说并不是必需的,但在主动查找和纠正此类代码中的错误方面非常有用。

答案 4 :(得分:7)

它们在语义上是相同的。我怀疑性能有什么不同,所以选择的是风格和可读性。如果您很好奇,请将上面的代码编译成一个程序集并使用Reflector来查看IL中是否存在任何差异。我的猜测是否会有任何差别。

答案 5 :(得分:6)

这主要是一个偏好问题。当使用return语句时,我认为你不需要elses,因为很明显函数在那里结束。这一切都与情况和风格有关,因此没有明确的“最佳”方式。

答案 6 :(得分:5)

您想使用“else if”,因为只有在第一个“if”不被接受时才会触发。在你的情况下,3 if语句是可以的,只是因为如果后者“if”是正确的,那么之前的“if”s不能。

如果你的所有if语句都是正确的,你可以使用else if。

例如:

if (8<10) {
return 10;
}
if (8<9) {
return 9;
}

这是一个非常简单的例子,但你明白了。当你只想要一个“if”语句时,你可以使用“else if”。

答案 7 :(得分:5)

我建议前者,因为你在四种可能性之间做出了合理的选择。您正在将决策分组到一个if / else if块中。

如果您将第二个功能中的决定分开,则它们似乎根本没有连接。显然,它们是重复的价值变量,但它可能不一定是显而易见的。

此外,如果您没有任何回报,请返回null,而不是空字符串。在我维护的应用程序中,仍然需要使用if(value == null || value!=“”)。

答案 8 :(得分:4)

替代方案在语义上非常接近,所以它并不重要。正如在一些答案中所建议的那样,将结果放在字符串变量中并在结尾处返回可能更好地表示您在方法中所做的事情。

另一种选择是使用条件操作数,它为您提供了一个不那么详细的代码:

protected string GetNumberDescription(int value) {
  return
    value >= veryBigNumber ? veryBigNumberDescription :
    value >= bigNumber ? bigNumberDescription :
    value >= smallNumber ? smallNumberDescription :
    String.Empty;
}

答案 9 :(得分:4)

protected string GetNumberDescription(int value) 
{ 
    return new NumberDescriptor(value).toString();
} 

您只需要隐藏自己的逻辑。 不要太认真,但是......我会这样做。我知道,你的问题在这里没有得到解决,但是在这个主题中已经有足够的if / then / else例子了。

答案 10 :(得分:4)

使用return语句,这无关紧要。我完全不同意那些说第二种情况更糟糕的人。是什么让它变得更糟?

回答你的第二个问题:你是对的。事实上,格式化if / else if 的两种方式不仅有效相同;他们实际上字面相同。 C#不强制执行特定的格式化样式,因此它们都是相同的:

// This...
if (A())
    return "Congrats!";
else if (B())
    return "Not bad!";
else if (C())
    return "Next time...";
else
    return "Uh-oh.";

// ...is the same as this...
if (A())
    return "Congrats!";
else
    if (B())
        return "Not bad!";
    else
        if (C())
            return "Next time...";
        else
            return "Uh-oh.";

// ...which is the same as this...
if (A()) return "Congrats!"; else
                       if               (B())
             return "Not bad!";


else
{ if
(C())


     return


"Next time...";else{
return "Oh-oh.";
}}

答案 11 :(得分:4)

1) 第一个更普遍,也是常见的做法。所以坚持标准做法是明智的。

2) 通常,当我们有多个条件语句时,else if用于中间条件输出,否则用于最后一个条件输出。此外,它可能更有效率,因为我认为它不必每次都检查相同的条件,而不像if-else-if-else ...类型。

它更像是一个提供给你的选择,你可以从许多路径到达同一目的地。但是,由于许多用户和专家的经验,您经常听到或看到的选择很受欢迎。

答案 12 :(得分:4)

我会使用第一个选项,因为它在代码中显示比较被“分组”一些。对于2,我认为它们最终完全相同的IL代码。

我总是确保最常见的senario首先出现在if..else语句中,因为这对性能最佳。

答案 13 :(得分:3)

如果函数被认为是返回四种可能性中的一种,我会说使用第一种,所有这些都被认为是“成功的”。如果某些返回表示“失败”,我会使用后一种风格。例如(玩具示例 - 对于错误情况,投掷可能更好):

string get_suit_name(int suit)
{
  string suit_names[4] = {"clubs", "diamonds", "hearts", "spades"};

  if (0 > suit) /* Avoid LT sign */
    return "Suit is improperly negative!";
  if (suit >= 4)
    return "Suit is too big!";
  return suit_names[suit];
}

答案 14 :(得分:3)

从我的观点来看,这将是从最高到最低的优先事项。

功能/实现最终目标 降低任何范围/级别的成本 可读性

^^^^请注意,很多人会在我的清单上对此提出异议,并将可读性称为降低成本,这实际上取决于您的工作环境。最终的目标,但我发现这是最常见的。但猜测来自一个并不意味着什么的新秀:D

之后你就是花生。同样如此? :运营商。如果你确信它更具可读性,那就去吧。功能方面它并不重要。但是if(){} else {}与if(){}显着不同if(){}那么选择什么是最佳代码(最高通缉结果减去意外结果 - 0.5 *可读性分数)几乎就是我要去的上。

现在看到代码对你来说是一样的,一个新的属性开始发挥作用,这段代码会在稍后阶段进行编辑吗?如果是这样,那么最好的是什么呢?不要忘记代码的未来,也不要忘记随意挑选的免费奖金。你甚至可以做到这两点,如果你不能弄清楚时间,只是评论另一个,但这确实会在稍后的清理/发布中删除草率的文本墙。

答案 15 :(得分:3)

对于提供的示例,如果您愿意牺牲大量的可读性并且可能有一点速度,则无需担心“if”语句:

string [] descriptions = {"", smallNumberDescription, bigNumberDescription, veryBigNumberDescription};

protected string GetNumberDescription(int value)
{
    int index = Convert.ToInt32(value >= smallNumber) + Convert.ToInt32(value >= bigNumber)
                + Convert.ToInt32(value >= veryBigNumber);
    return descriptions[index];
}

答案 16 :(得分:3)

在性能方面,它们可能是相同的,具体取决于编译器/解释器。在我看来,第二个更好......更容易调试。

答案 17 :(得分:1)

嗯,在您的具体情况下,我会建议:

protected string GetNumberDescription(int value) {
    if (value >= veryBigNumber)
        return veryBigNumberDescription;
    if (value >= bigNumber)
        return bigNumberDescription;
    if (value >= smallNumber)
        return smallNumberDescription;

    return "";

}

因为,你在任何真实条件下从函数返回,所以不需要使用'else if'。通常,当两个条件不相互排斥时使用'else if',这不是这里的情况。在您的情况下,如果任何条件成立,代码将不会进一步执行。 此外,最后的'else'不是必需的,因为只有当所有上述条件都为假时,控件才会到达该点。

这都是你在哪里使用它,以及如何使用它。主要动机是最大限度地提高代码的可读性,使其尽可能优雅且易于理解。