【问题标题】:Which syntax is better for return value?哪种语法更适合返回值?
【发布时间】:2010-09-13 11:24:37
【问题描述】:

我一直在进行大规模的代码审查,我注意到的一种模式是:

public bool MethodName()
{
    bool returnValue = false;
    if (expression)
    {
        // do something
        returnValue = MethodCall();
    }
    else
    {
        // do something else
        returnValue = Expression;
    }

    return returnValue;
}

这不是我会这样做的方式,当我知道它是什么时,我会返回该值。这两种模式哪个更正确?

我强调,逻辑似乎总是这样结构化,即返回值仅在一个地方分配,分配后不执行任何代码。

【问题讨论】:

    标签: coding-style return-value


    【解决方案1】:

    很多人建议您的方法中只有一个退出点。您在上面描述的模式遵循该建议。

    该建议的主要要点是,如果您必须在从方法返回之前清理一些内存或状态,最好只将这些代码放在一个地方。拥有多个退出点会导致清理代码重复或由于一个或多个退出点缺少清理代码而导致潜在问题。

    当然,如果你的方法有几行长,或者不需要任何清理,你可以有多个返回。

    【讨论】:

      【解决方案2】:

      我会使用三元来减少控制结构...

      return expression ? MethodCall() : Expression;

      【讨论】:

      • 你在 return 语句之前做了不同的事情,因此 // 做某事和 // 做其他事情。
      【解决方案3】:

      我怀疑我会是少数,但我喜欢示例中呈现的风格。添加日志语句并设置断点很容易,IMO。此外,当以一致的方式使用时,“模式匹配”似乎比多次返回更容易。

      不过,我不确定是否有“正确”的答案。

      【讨论】:

        【解决方案4】:

        一些学习机构和书籍提倡单一返回的做法。

        好不好是主观的。

        【讨论】:

        • 压倒性的共识似乎是情况更糟。
        【解决方案5】:

        这看起来像是糟糕的 OOP 设计的一部分。也许它应该在比单个方法内部更高的层次上进行重构。

        否则,我更喜欢使用三元运算符,如下所示:

        return expression ? MethodCall() : Expression;
        

        它更短,更易读。

        【讨论】:

        • 如果你必须查看我正在审查的代码,你会认为这是糟糕的 OOP 设计中最不重要的实例......大部分代码都在一个名为 Form1.cs 的文件中大约有 4k 行长……它让我头疼,完全是在摧毁灵魂。
        【解决方案6】:

        在任何这些情况下立即从方法返回:

        1. 您发现了一个边界条件,需要返回一个唯一值或标记值:if (node.next = null) return NO_VALUE_FOUND;
        2. 所需的值/状态为假,因此该方法的其余部分不适用(也称为保护子句)。例如:if (listeners == null) return null;
        3. 该方法的目的是查找并返回一个特定的值,例如:if (nodes[i].value == searchValue) return i;
        4. 您在一个子句中,该子句从方法中其他地方未使用的方法返回唯一值:if (userNameFromDb.equals(SUPER_USER)) return getSuperUserAccount();

        否则,只有一个 return 语句很有用,以便更容易添加调试日志记录、资源清理和遵循逻辑。我尝试先处理上述所有 4 种情况,如果它们适用,然后尽可能晚地声明一个名为 result(s) 的变量,并根据需要为其赋值。

        【讨论】:

          【解决方案7】:

          他们都完成了相同的任务。有人说一个方法应该只有一个入口和一个出口点。

          【讨论】:

            【解决方案8】:

            我也用这个。这个想法是可以在程序的正常流程中释放资源。如果你在 20 个不同的地方跳出一个方法,并且之前需要调用 cleanUp(),你将不得不添加另一个清理方法 20 次(或重构所有内容)

            【讨论】:

              【解决方案9】:

              我猜编码器已经采取了在方法顶部定义一个对象 toReturn 的设计(例如,List toReturn = new ArrayList();),然后在方法调用期间填充它,并以某种方式决定将其应用于布尔返回类型,这很奇怪。

              也可能是编码标准的副作用,即不能在方法主体的中间返回,只能在末尾返回。

              【讨论】:

              • 是的,它通常是我正在查看的代码中的字符串或布尔值,但它可以是任何对象类型。我只使用 bool 是因为我遇到的最后一个示例(5 inutes 前)是 bool。没有返回其他对象的原因是因为设计很垃圾,里面的对象很少。
              【解决方案10】:

              即使现在分配返回值后没有执行任何代码,但这并不意味着以后不必添加某些代码。

              这不是可以使用的最小的代码段,但它对重构非常友好。

              【讨论】:

                【解决方案11】:

                Delphi 通过自动创建一个名为“Result”的变量来强制这种模式,该变量将是函数的返回类型。无论函数退出时的“结果”是什么,都是您的返回值。所以根本没有“return”关键字。

                function MethodName : boolean;
                begin
                  Result := False;
                  if Expression then begin
                    //do something
                    Result := MethodCall;
                  end
                  else begin
                    //do something else
                    Result := Expression;
                  end;
                
                  //possibly more code
                end;
                

                【讨论】:

                  【解决方案12】:

                  使用的模式很冗长 - 但如果您想知道返回值而不打开 Registers 窗口并检查 EAX,它也更容易调试。

                  【讨论】:

                    猜你喜欢
                    • 2017-06-06
                    • 1970-01-01
                    • 2014-05-06
                    • 1970-01-01
                    • 2017-04-11
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2015-12-31
                    相关资源
                    最近更新 更多