4

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

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

    return returnValue;
}

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

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

4

12 回答 12

3

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

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

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

于 2008-09-26T14:15:14.527 回答
2

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


return expression ? MethodCall() : Expression;

于 2008-09-26T14:11:24.597 回答
2

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

但是,我不确定对此是否有“正确”的答案。

于 2008-09-26T14:13:16.327 回答
1

That looks like a part of a bad OOP design. Perhaps it should be refactored on the higher level than inside of a single method.

Otherwise, I prefer using a ternary operator, like this:

return expression ? MethodCall() : Expression;

It is shorter and more readable.

于 2008-09-26T14:16:01.060 回答
1

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

好不好是主观的。

于 2008-09-26T14:12:48.043 回答
1

在以下任何一种情况下立即从方法返回:

  1. 您找到了一个边界条件,需要返回一个唯一值或标记值:if (node.next = null) return NO_VALUE_FOUND;
  2. 所需的值/状态为 false,因此该方法的其余部分不适用(也称为保护子句)。例如: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)尽可能晚地声明一个变量,并根据需要为其赋值。

于 2008-10-20T05:35:44.620 回答
0

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

于 2008-09-26T14:39:32.143 回答
0

Delphi forces this pattern by automatically creating a variable called "Result" which will be of the function's return type. Whatever "Result" is when the function exits, is your return value. So there's no "return" keyword at all.

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;
于 2008-09-26T14:17:01.060 回答
0

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

于 2008-09-26T14:12:39.603 回答
0

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

于 2008-09-26T14:12:52.223 回答
0

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

也可能是编码标准的副作用,该标准规定您不能在方法主体的中间返回,只能在最后。

于 2008-09-26T14:13:53.483 回答
0

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

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

于 2008-09-26T14:14:42.080 回答