Delphi FreeAndNil:寻找替代实现

2023-12-13

注意:请耐心听我说,我感觉有点「火焰烤」由于一些讨论here and here以及我报告的一些问题here and here.

一些背景

旧的(10.4 之前)FreeAndNil看起来像这样:

FreeAndNil(var SomeObject)

新的和新鲜的FreeAndNil看起来像这样:

FreeAndNil(const [ref] SomeObject: TObject);

IMO 都有各自的缺点:

  • 旧的不做任何类型检查,所以调用FreeAndNil在指针、记录和接口上编译得很好,但在运行时会产生有趣但通常不需要的效果。 (完全疯狂,或者如果你幸运的话,它会因 EAccessViolation、EInvalidOperation 等而停止。)
  • 新的接受一个 const 参数,因此也接受任何对象。但随后提供的对象指针实际上是使用一些更改的古怪的代码.
  • 您现在可以调用新的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直接地。 我做什么not非常喜欢的是:

  • 类型检查在运行时进行,并且仅在断言为 ON 时进行。
  • 感觉就像必须传递同一个变量两次。这不一定是真的/必需的。它必须是同一个对象,并且参数必须是变量。

另一项调查

但如果可以不带参数调用该多好

var MyObj:=TSomeObject.Create;
...
MyObj.FreeAndNil;

所以我乱搞了self指针并设法将其设置为nil使用 10.4 中使用的相同 Hacky-Wacky 代码FreeAndNil。嗯...这有效inside方法,self指向nil。但打电话之后FreeAndNil像这样,MyObj 变量不是 nil,而是一个过时的指针。 (这正是我所期望的。)此外,MyObj可以是属性或例程(的结果)、构造函数等。

so nope这里也...

最后的问题是:

您能想到一个更干净/更好的解决方案或技巧吗:

  • FreeAndNil(var aObject:TObject) 具有不太严格的类型检查编译时(可能是编译器指令?),因此它允许编译和调用变量any对象类型。
  • 当某些东西通过时抱怨编译时间not某种对象类型的变量/字段
  • 帮助描述什么是最好的解决方案/要求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);
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Delphi FreeAndNil:寻找替代实现 的相关文章

  • 在 RESTful Web 服务中实现注销

    我正在开发一个需要注销服务的移动应用程序 登录服务是通过数据库验证来完成的 现在我陷入了注销状态 退一步 您没有提供有关如何在应用程序中执行身份验证的详细信息 并且很难猜测您在做什么 但是 需要注意的是 在 REST 应用程序中 不能有会话
  • Antlr 解析器运算符优先级

    考虑以下语法 我对运算符优先级有疑问 例如 res 2 a b有一个类似的解析树res 2 a b 我知道问题出在哪里 但我没有想到没有相互左递归的 漂亮 解决方案 你能帮我一点忙吗 该语法与自定义访问者一起使用 grammar Math
  • 如何通过索引访问 JSON 对象中的字段

    我知道这不是最好的方法 但我别无选择 我必须通过索引访问 JSONObject 中的项目 访问对象的标准方法是只写this objectName or this objectName 我还找到了一种获取 json 对象内所有字段的方法 fo
  • 带有 Maven Wrapper 的 Java 17 导致无法识别的 VM 选项“MaxPermSize=512m”

    I use OpenJDK 17 https jdk java net 17 使用 Maven Wrapper 3 8 2 从春季初始化 https start spring io Maven项目 JAR打包 Java 17 Spring
  • MySQL 查询计算上个月

    我想计算上个月的订单总额 我收到了从当前日期获取当月数据的查询 SELECT SUM goods total AS Total Amount FROM orders WHERE order placed date gt date sub c
  • 没有输入的 jQuery 日期选择器

    我有一个相当复杂的网络应用程序 我想向其中添加一些日期选择 UI 我遇到的问题是我无法从文档中弄清楚如何真正控制日期选择器的出现方式和时间 不涉及任何表单元素 不 我不会添加秘密表单字段 因此简单的开箱即用方法根本行不通 我希望有人可以提供
  • PrimeFaces 对话框参考父级

    我有一个 xhtml 页面 显示带有条目的数据表 我还有一个用于插入新条目的按钮 该按钮显示一个包含表单的对话框 插入表格用作
  • 类型或命名空间“MyNamespace”不存在等

    我有通常的类型或命名空间名称不存在错误 除了我引用了程序集 using 语句没有显示为不正确 并且我引用的类是公共的 事实上 我在不同的解决方案中引用并使用相同的程序集来执行相同的操作 并且效果很好 顺便说一句 这是VS2010 有人有什么
  • Pandas 与 Numpy 数据帧

    看这几行代码 df2 df copy df2 1 df 1 df 1 values 1 df2 ix 0 0 我们的教练说我们需要使用 values属性来访问底层的 numpy 数组 否则我们的代码将无法工作 我知道 pandas Data
  • Mono 应用程序在非阻塞套接字发送时冻结

    我在 debian 9 上的 mono 下运行一个服务器应用程序 大约有 1000 2000 个客户端连接 并且应用程序经常冻结 CPU 使用率达到 100 我执行 kill QUIT pid 来获取线程堆栈转储 但它总是卡在这个位置
  • 现代编译器是否优化乘以 1 和 -1

    如果我写 template
  • 将第三个表链接到多对多关联中的桥接表

    设计这个数据库的正确方法是什么 这是我设置表格的方式 我在名为 教师 的表和名为 仪器 的表之间存在多对多关系 然后我有一个连接两者的桥接表 我想将另一个表与 BRIDGE 表关联起来 意思是乐器 老师的组合 该表有 3 行 指定老师可以教
  • Amazon RDS for SQL Server 是否支持 SSIS?

    从谷歌搜索中读到一些相互矛盾的答案 不确定答案是是 否还是可能 我觉得读的时候已经很清楚了this http docs aws amazon com AmazonRDS latest UserGuide CHAP SQLServer htm
  • NSArrayController 无需将大型数据集加载到数组中

    我想使用 NSArrayController 向 NSTableView 提供数据 我面临的问题是我不想将所有数据预先加载到数组中 然后使用数组控制器setContent 方法 我的数据模型是一个管理数百万条记录的大型现有代码库 它包含有效
  • 一种无需 JavaScript 即可在 PHP 中确定浏览器宽度的方法?

    首先有吗 或者我必须使用javascript 我希望能够更改使用的 CSS 因此 frex 我可以为移动设备或其他设备加载较小的字体 不幸的是 仅使用 PHP 无法检测用户分辨率 如果您使用 Javascript 则可以在 cookie 中
  • 如何在 Angular 4 中翻译 mat-paginator?

    你知道如何在 Angular 中翻译 每页项目 吗mat paginator标签 这mat paginator是材料设计中的一个元素 您可以使用MatPaginatorIntl为了这 威尔 豪厄尔制作 https github com an
  • 如何修复:“无法解析类型 java.lang.CharSequence。它是从所需的 .class 文件间接引用的”消息? [复制]

    这个问题在这里已经有答案了 我正在尝试使用这个字符串 amountStr amountStr replace replace replace 但我收到一条错误消息 我知道我收到的错误消息是因为我刚刚发布的字符串已过时 所以我想知道该字符串的
  • 如何在 OSX 上安装 LaTeX .sty 文件?

    我设置了一个 LaTeX 项目 tex documents some file tex support todonotes sty where some file tex uses todonotes usepackage colorinl
  • Android 材料芯片组件崩溃应用程序。无法膨胀 xml

    Tried Chip来自两个支持库的组件 com google android support design 28 0 0 rc01和材料 com google android material material 1 0 0 rc01 堆栈
  • 探查器模板可以迁移到较新版本的 SQL Profiler 吗?

    是否可以将 Profiler 模板迁移到较新版本的 SQL Server 就我而言 我想将 SQL 2008 模板带到 2012 年 我尝试过 1 直接文件复制和 2 导出 导入 在这两种情况下 旧模板都会运行 但无法修改 修改后会出现以下

随机推荐

  • 运行 git init 两次是否会初始化存储库或重新初始化现有存储库?

    当您发出命令时 现有的 git 存储库会发生什么git init again 我创建了一个存储库git init 创建文件 添加 提交 检查状态 没有要提交的内容 然后创建另一个文件 检查状态 我可以看到它没有按预期被跟踪 然后 错误地说
  • 为什么当我创建新存储库时 github 显示灰色文件夹?

    git命令 git init git add git commit m project git remote add origin https github com git push u origin master 灰色文件夹 github
  • MySql 使用哪种数据结构? [关闭]

    很难说出这里问的是什么 这个问题模棱两可 含糊不清 不完整 过于宽泛或言辞激烈 无法以目前的形式合理回答 如需帮助澄清此问题以便重新打开 访问帮助中心 MySql 使用哪种数据结构 可能很多 但从 B 树开始
  • 页面刷新后如何保留div内容

    我正在使用 Jquery 创建一个动态 div 并且尝试缓存它 以便在页面刷新后将其取回 请帮助了解如何实现这一点 粘贴下面的代码
  • 增加PHP中的max_execution_time?

    我正在尝试将大文件上传到我的服务器 我的服务器支持post max size192mb 和max execution time600 秒 当我上传 100mb 文件时 执行将在 600 秒后停止 因此文件不会上传到服务器 我怎样才能增加ma
  • 如何获取 geom_segment 显示图例

    我有下面的图 有 2 段 如何为线段添加图例 理想情况下 最终结果有 2 个图例 其中之一就是当前的 点图例 另一个图例是单个图例 带有红色虚线标记为 段图例 这是代码 set seed 11 x rnorm 100 y rnorm 100
  • 如何有效地知道字符中第一个(左 -> 右)“1”位的位置[重复]

    这个问题在这里已经有答案了 正如标题所说 我有一个字符 例如00101011 我如何知道其中第一个 1 位的位置 在本例中 它是 6 如果我们认为最右边的位置是 0 则它是 5 我知道 for 循环移位会有所帮助 但是有更有效的方法吗 有一
  • 替换字符串中的变量占位符

    我的字符串看起来像这样 您可以使用促销直到 开始日期 30 我需要更换 Start Date 30 带有实际日期的占位符 即销售的开始日期加上 30 天 或任何其他数字 Start Date 也可能单独出现而不添加编号 此外 占位符内的任何
  • SASS 变量和继承

    假设我有两个几乎相同的 HTML 结构 但具有不同的class名称 它们仅存在几个变量不同 例如width and height 通过使用 SASS SCSS 变量 我想我可以做这样的事情 widget a width 50px widge
  • iOS 6 Facebook 登录不刷新访问令牌

    我正在阅读的任何内容 许多 FB 开发文章和 SO 问题 都没有帮助 所以我想我应该在这里发帖 我正在尝试让这一切与 iOS 6 和 Facebook SDK 3 1 1 一起使用 我有一个非常基本的设置 我的 iOS 应用程序通过 Fac
  • 请帮我找出这个网络代理代码有什么问题

    我想编写一个网络代理来练习 这是我到目前为止的代码 returns a map that contains the port and the host def parseHostAndPort String data def objMap
  • 加快 Gatsby 性能

    我在工作中接到了一项提高项目绩效的任务 目前 Google Lighthouse 分数有所波动 但总体而言 分数并不是那么好 因此我们正在尝试找出如何提高其性能 以便能够向我们的领导者炫耀 我们的项目将整个 Gatsby 站点作为单个 Ja
  • PHP 中如何将十六进制转换为二进制?

    我正在尝试发送0x01十六进制作为字节使用socket write socket XXXX 1 功能 有部分文档 如果是 服务器将回复模块 0x01 如果不是 重播 0x00 服务器必须发送答案 1 字节十六进制格式 有多种选择 当使用pa
  • 画布动画中的闪烁图像

    window requestAnimFrame function callback return window requestAnimationFrame window webkitRequestAnimationFrame window
  • 在ipython中调用pylab.savefig而不显示

    我需要在文件中创建一个图形 而不在 IPython 笔记本中显示它 我不清楚之间的相互作用IPython and matplotlib pylab在这方面 但是 当我打电话时pylab savefig test png 除了保存在中之外 还
  • K&R fopen 和 fillbuf 中的 C 段错误

    我对C很陌生 我在学习K R最后一章时遇到了一个问题 我正在尝试实施fopen and fillbuf 通过使用系统调用来实现功能 open and read 我完全复制了书中的源代码 但编译后反复出现分段错误 fp gt fd fd fp
  • 如何保证三个DIV无论内容如何高度相同

    div class section group div class col span 1 of 3 articleTeaserBoxColor div class test2n div class imgHolder img class i
  • 遍历所有表单元素,无论其类型如何

    我正忙于为我们的一位客户提供表单管理器 总体想法是为各个部门构建表单 我想创建一个微型系统来处理表单的验证等 而无需重做太多工作 尽可能自动化 我的第一个主要任务是 我想单击提交按钮 迭代整个表单 并根据特定的凭据和验证规则验证表单 然后再
  • ?:??运算符代替 IF|ELSE

    public string Source get if Source null return string Empty else return Source return Source string Empty set if Source
  • Delphi FreeAndNil:寻找替代实现

    注意 请耐心听我说 我感觉有点 火焰烤 由于一些讨论here and here以及我报告的一些问题here and here 一些背景 旧的 10 4 之前 FreeAndNil看起来像这样 FreeAndNil var SomeObjec