Delphi 返回对象时为什么不直接使用结果变量?

Delphi 返回对象时为什么不直接使用结果变量?,delphi,Delphi,我在很多例子中看到,创建一个与结果类型相同的变量,并在函数末尾赋给它,而不是一开始就使用结果变量 例如,在System.JSON内部的代码中 class function TJSONObject.ParseJSONValue( const Data: TArray<Byte>; const Offset: Integer; const ALength: Integer; Options: TJSONParseOptions ): TJSONValue; var

我在很多例子中看到,创建一个与结果类型相同的变量,并在函数末尾赋给它,而不是一开始就使用结果变量

例如,在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;
类函数TJSONObject.ParseJSONValue(
常数数据:TArray;
常数偏移量:整数;
常数长度:整数;
选项:TJSONParseOptions
):TJSONValue;
变量
家长:TJSONArray;
答:TJSONValue;
Br:TJSONByteReader;
开始
父项:=TJSONArray.Create;
答案:=零;{为什么不直接在这里使用Result?}
Br:=TJSONByteReader.Create(
数据,
抵消,
阿伦特,
选项中的TJSONParseOption.IsUTF8
);
尝试
用户空白(Br);
如果
(ParseValue(Br,父项,TJSONParseOption.UseBool-in-Options)=ALength)
和
(Parent.Count=1)
然后
回答:=Parent.Pop;{为什么不直接在这里使用Result?}
结果:=答案;
最后
父母。免费;
Br.免费;
结束;
结束;
为什么要创建变量答案而不是仅仅使用结果

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

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

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

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;
类函数TJSONObject.ParseJSONValue(
常数数据:TArray;
常数偏移量:整数;
常数长度:整数;
选项:TJSONParseOptions
):TJSONValue;
变量
家长:TJSONArray;
Br:TJSONByteReader;
开始
父项:=TJSONArray.Create;
尝试
Br:=TJSONByteReader.Create(
数据,
抵消,
阿伦特,
选项中的TJSONParseOption.IsUTF8
);
尝试
用户空白(Br);
if(ParseValue(Br,父项,TJSONParseOption.UseBool in Options)=ALength)
和(Parent.Count=1)然后
结果:=Parent.Pop
其他的
结果:=无;
最后
Br.免费;
结束;
最后
父母。免费;
完:
结束;

这还纠正了生命周期管理和潜在的内存泄漏,如注释中所述

雇佣的java程序员太多,不熟悉Object Pascal语法?这两种方法都很好,只是编码风格的问题。如果愿意,您当然可以直接使用
结果。不管是哪种方式,只要确保在函数退出之前发生错误时调用输出对象上的
Free
,否则您将发生内存泄漏(上面的代码没有这种保护,这让Embarcadero感到羞耻!)@RemyLebeau怎么会发生这种泄漏?
Answer:=Parent.Pop
之后必须出现异常。可以安全地假设没有。当然,
Parent
很容易泄漏。@DavidHeffernan:
Parent
TJSONByteReader.Create
引发异常时泄漏。@DavidHeffernan在本例中,输出对象没有泄漏,是的。但通常,如果为输出创建对象,然后在函数退出之前引发异常,请确保销毁输出对象,否则它将泄漏。这就是我最初的评论想要表达的。