【问题标题】:Why not use the Result variable directly when returning object?返回对象时为什么不直接使用 Result 变量?
【发布时间】:2018-04-17 19:59:59
【问题描述】:

我在很多示例中看​​到创建一个与 Result 具有相同类型的变量并在函数末尾分配给它,而不是一开始就使用 Result 变量。

例如在 System.JSON 中的代码中

class function TJSONObject.ParseJSONValue(
  const Data: TArray<Byte>; 
  const Offset: Integer; 
  const ALength: Integer; 
  Options: TJSONParseOptions
): TJSONValue;
var
  Parent: TJSONArray;
  Answer: TJSONValue;
  Br: TJSONByteReader;
begin
  Parent := TJSONArray.Create;
  Answer := nil; { Why not just use Result directly here? }
  Br := TJSONByteReader.Create(
          Data, 
          Offset, 
          ALength, 
          TJSONParseOption.IsUTF8 in Options
  );
  try
    ConsumeWhitespaces(Br);
    if 
      (ParseValue(Br, Parent, TJSONParseOption.UseBool in Options) = ALength) 
      and
      (Parent.Count = 1)
    then
      Answer := Parent.Pop; { Why not just use Result directly here? }
    Result := Answer; 
  finally
    Parent.Free;
    Br.Free;
  end;
end;

为什么要创建变量 Answer 而不是只使用 Result?

这只是程序员决定这样做的方式还是有其背后的原因?

【问题讨论】:

  • 招聘的java程序员太多,不熟悉Object Pascal语法?
  • 任何一种方法都可以正常工作,这只是编码风格的问题。如果您愿意,您当然可以直接使用Result。无论哪种方式,如果在函数退出之前发生错误,请确保在输出对象上调用Free,否则您将发生内存泄漏(上面的代码没有这种保护 - Embarcadero 对此感到羞耻!)。
  • @RemyLebeau 这怎么会泄露?在Answer := Parent.Pop 之后必须有一个例外。可以安全地假设不存在。当然,Parent 很容易被泄露引用。
  • @DavidHeffernan: 如果TJSONByteReader.Create 引发异常,Parent 就会泄露。
  • @DavidHeffernan 在这个例子中,输出对象没有泄露,是的。但总的来说,如果你为输出创建了一个对象,然后在函数退出之前引发了异常,请确保销毁输出对象,否则它将被泄漏。这就是我最初的评论想要表达的意思。

标签: delphi


【解决方案1】:

这只是程序员决定这样做的方式还是背后有原因?

这里没有充分的理由使用额外的局部变量。这样做只会增加复杂性。我会这样写:

class function TJSONObject.ParseJSONValue(
  const Data: TArray<Byte>; 
  const Offset: Integer; 
  const ALength: Integer; 
  Options: TJSONParseOptions
): TJSONValue;
var
  Parent: TJSONArray;
  Br: TJSONByteReader;
begin
  Parent := TJSONArray.Create;
  try
    Br := TJSONByteReader.Create(
      Data, 
      Offset, 
      ALength, 
      TJSONParseOption.IsUTF8 in Options
    );
    try
      ConsumeWhitespaces(Br);
      if (ParseValue(Br, Parent, TJSONParseOption.UseBool in Options) = ALength)
      and (Parent.Count = 1) then
        Result := Parent.Pop
      else
        Result := nil; 
    finally
      Br.Free;
    end;
  finally
    Parent.Free;
  end:
end;

这也纠正了生命周期管理和潜在的内存泄漏,如 cmets 中所述。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-04-14
    • 1970-01-01
    • 2020-11-15
    • 2013-08-08
    • 2020-05-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多