gpt4 book ai didi

Delphi FreeAndNil : Looking for an alternate implementation

转载 作者:行者123 更新时间:2023-12-03 20:05:37 24 4
gpt4 key购买 nike

注意:请耐心等待,由于对 here 的一些讨论,我感到有点“被烤焦”了。和 here以及我报告的一些问题 herehere .
一些背景
老叶(10.4 之前)FreeAndNil看起来像这样:

FreeAndNil(var SomeObject)
新鲜出炉 FreeAndNil看起来像这样:
FreeAndNil(const [ref] SomeObject: TObject);
IMO 都有其缺点:
  • 旧的不做任何类型检查,所以调用 FreeAndNil on 指针、记录和接口(interface)编译得很好,但在运行时会产生有趣但通常不需要的效果。 (完全发疯,或者如果幸运的话,它会因 EAccessViolation、EInvalidOperation 等而停止。)
  • 新的接受一个 const 参数,因此接受任何对象。但是随后提供的对象指针实际上是使用一些 hacky-wacky 代码更改的。
  • 您现在可以调用新的 FreeAndNil像这样:FreeAndNil(TObject.Create)它会编译甚至运行得很好。我喜欢旧的 FreeAndNil当我出错时警告我并提供例如属性而不是字段。不确定如果您为此 FreeAndNil 提供对象类型属性会发生什么执行。没试过。

  • 如果我们将签名更改为 FreeAndNil(var SomeObject:TObject)那么它将不允许我们传递任何其他变量类型,那么正是 TObject类型。这也是有道理的,好像它不是 FreeAndNil ,可以轻松更改类型为 TComponent 的变量。在例程中将 var 变量更改为完全不同类型的对象,例如 TCollection .当然 FreeAndNil不会做这样的事情,因为它总是将 var 参数更改为 nil。
    所以这使得 FreeAndNil一个特例。
    甚至可能特别到足以说服 delphi 添加编译器魔法 FreeAndNil执行?投票给任何人?
    潜在的解决方法
    我想出了下面的代码作为替代方案(这里作为辅助方法,但也可以作为 TObject 实现的一部分),它结合了两个世界。 Assert将有助于在运行时查找无效调用。
    procedure TSGObjectHelper.FreeAndNilObj(var aObject);
    begin
    if Assigned(self) then
    begin
    Assert(TObject(aObject)=self,ClassName+'.FreeAndNil Wrong parameter provided!');
    pointer(aObject):=nil;
    Destroy;
    end;
    end;
    用法将是这样的:
    var MyObj:=TSOmeObject.Create;
    ...
    MyObj.FreeAndNilObj(MyObj);
    我已经实际测试过这个例程,它甚至比 10.4 FreeAndNil 稍微快一点。执行。我猜是因为我先做作业检查并调用 Destroy直接地。
    我不太喜欢的是:
  • 类型检查在运行时进行,并且仅在断言为 ON 时进行。
  • 感觉就像必须两次传递相同的变量。这不一定是正确的/必需的。它必须是同一个对象,并且参数必须是变量。

  • 另调查
    但是如果一个人可以在没有参数的情况下调用,那不是很好吗
    var MyObj:=TSomeObject.Create;
    ...
    MyObj.FreeAndNil;
    所以我搞砸了 self指针并设法将其设置为 nil使用 10.4 在其 FreeAndNil 中使用的相同 Hacky-Wacky 代码.嗯...在方法中有效, self指向 nil .但是在调用 FreeAndNil之后像这样,MyObj 变量不是 nil,而是一个过时的指针。 (这是我的预期。)此外, MyObj可以是属性或(的结果)例程、构造函数等。
    所以这里也不行……
    最后是问题:
    您能想出一个更清洁/更好的解决方案或技巧吗:
  • FreeAndNil(var aObject:TObject) 具有不那么严格的类型检查编译时间(可能是编译器指令?),因此它允许编译和调用任何对象类型的变量。
  • 当传递的东西不是某个对象类型的变量/字段时,提示编译时间
  • 帮助描述 RSP-29716 中的最佳解决方案/要求是什么?
  • 最佳答案

    FreeAndNil 的唯一正确解决方案这既是类型安全的又不允许释放函数结果和属性将是通用 var 参数:

     procedure FreeAndNil<T: class>(var Obj: T); inline;
    但是,目前 Delphi 编译器不允许在独立过程和函数上使用泛型 https://quality.embarcadero.com/browse/RSP-13724
    不过,这并不意味着您不能拥有通用 FreeAndNil实现,只是它会比必要的更冗长。
    type
    TObj = class
    public
    class procedure FreeAndNil<T: class>(var Obj: T); static; inline;
    end;

    class procedure TObj.FreeAndNil<T>(var Obj: T);
    var
    Temp: TObject;
    begin
    Temp := Obj;
    Obj := nil;
    Temp.Free;
    end;
    Rio 中引入的类型推断将允许您在不指定通用签名的情况下调用它:
    TObj.FreeAndNil(Obj);
    调用(和使用)泛型 FreeAndNil在较旧的 Delphi 版本中也是可能的,但更冗长
    TObj.FreeAndNil<TFoo>(Obj);

    关于Delphi FreeAndNil : Looking for an alternate implementation,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62479148/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com