Delphi 11中的变体行为是否有所改变?

3
在Delphi 10.3中,我编写了一些Excel自动化代码。使用了变量(variants)。当程序结束时,我清除并使用freeAndNil释放该变量...
  VarClear(arrData);
  FreeAndNil(arrData);

这段代码之前可以正常编译和运行,但是我刚刚升级到了D11(Alexandria)版本后,会出现错误提示:“不兼容的类型:TObject 和 Variant。”
我重新修改了这部分代码为:
  VarClear(arrData);
  arrData.Free;

这段代码可以编译运行,并且乍一看似乎工作正常。这是清除/释放Alexandria变体的正确方式吗?


我没有D11,但根据您的描述,他们重新定义了FreeAndNil(var obj)procedure FreeAndNil(var Obj:TObject)。现在,由于Free是TObject的一个方法,与variant无关,除非他们为variants添加了帮助程序来引入“free”方法,否则这看起来非常不对。 - Ken Bourassa
3个回答

15

FreeAndNil() 的签名在 Delphi 10.4 中确实已经更改:

https://blog.marcocantu.com/blog/2020-may-delphi-104-rtl.html

我们更新了 FreeAndNil 过程的签名,以避免其与接口引用和其他不支持的数据类型一起使用。现在声明需要一个 TObject 的引用:

procedure FreeAndNil(const [ref] Obj: TObject); inline;

这意味着错误使用 FreeAndNil 现在会导致编译器错误。 在过去,错误使用不会被捕获,导致难以调试的错误。请注意,虽然参数声明为 const,但引用变量确实被修改。

首先,尝试 Free() 一个 Variant 是错误的。这从来没有起作用,也不应该在代码中出现。根据旧定义,FreeAndNil() 会在 Variant 上调用 TObject.Free(),这是错误的。根据您的新代码,arrData.Free; 将编译,但将在运行时调用方法分派来调用 Excel 对象上不存在的 Free() 方法,这将失败。

所以,完全删除 Free,它在这里不属于。在所有 Delphi 版本中,手动将 Variant 重置为默认状态的正确解决方案是将 Variants.NullVariants.Unassigned 赋值给它,例如:

arrData := Null;
arrData := Unassigned;

优秀的回答! - user1009073
FreeAndNil在调用(对象类型)属性时不会发出警告,这是非常错误的。Emb已经用另一个糟糕的解决方案来交换了一个糟糕的解决方案。请参见https://dev59.com/eLvoa4cB1Zd3GeqP9LhZ。 - H.Hasenack

6

这两个代码片段都是错误的。你不能在 variant 上调用 Free,只能在对象实例上调用。只需删除那一行即可。


2
在你告诉我这段代码曾经是可以工作的之前,我要说它从来就是错的,只是你以前没有被发现而已。 - David Heffernan

0

如果变量是指针数组,FreeAndNil 不是解决方案,而是使用 freemem。

FreeMem(PSomeArray);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接