【问题标题】:Is safe to cast a dynamic array before passing it as a variable parameter?在将动态数组作为可变参数传递之前是否可以安全地转换它?
【发布时间】:2018-03-20 11:05:36
【问题描述】:

我有一些函数接受TObject 数组作为var 参数,例如:

type
  TObjectArray = array of TObject;

...

procedure DeleteAt(var AArray : TObjectArray; AIndex : integer);
begin
  while(AIndex < Length(AArray) - 1) do
  begin
    AArray[AIndex] := AArray[AIndex + 1];
    Inc(AIndex);
  end;
  SetLength(AArray, Length(AArray) - 1);
end;

为了重用相同的函数,我将TObject 的后代类的几个动态数组转换为TObjectArray,然后再将它们传递给我的函数,例如:

var
  Buttons : array of TButton;
begin
  SetLength(Buttons, 1);
  Buttons[0] := Button1;

  //...

  DeleteAt(TObjectArray(Buttons), 0);
end;

这是一种安全的做法还是可能会导致一些我没有考虑过的问题?

【问题讨论】:

  • 如果你只转换与 TObject 兼容的数组,那么它可能会起作用。但无论如何,这很糟糕。为什么不使用通用 TList
  • @AndreiGalatyn:因为我使用的是 Delphi 2007
  • 您可以使用常规类 TList / TObjectList。
  • 当然你可以做得比这更好。但是,是的,这会成功的。
  • @DavidHeffernan:你能解释一下你的意思吗?

标签: arrays delphi casting dynamic-arrays delphi-2007


【解决方案1】:

只要阵列兼容,该技术本身不会造成伤害。 array of TObject 的成员只是对对象的引用。由于可以从祖先引用安全地使用对象,因此不存在固有问题。

当然,您在问题中显示的代码是安全的。如果这对您的所有权模式有意义,您甚至可以Free 要删除/删除的对象实例。


也就是说,存在编译器无法执行任何典型类型安全检查的风险。

  • 在极端情况下,您可以在 array of Bytearray of TObject 之间进行转换
  • 更微妙的是,您可能会意外地在不兼容对象类型的数组之间进行转换(例如,在 array of TButtonarray of TQuery 之间进行转换)。处理单个对象时,您可以选择使用(&lt;object&gt; as &lt;type&gt;) 进行检查类型转换。这将执行编译时检查以验证类型是否在同一层次结构内(否则保证强制转换不兼容),并执行运行时检查以确保对象实例实际上是正确的类型。
  • 虽然删除和交换数组中的对象是安全的,但 var 引用意味着您也可以向数组中添加对象。现在,array of TButton 强制您添加 TButton(或子类)实例;对array of TObject 进行类型转换意味着您可能会不小心将任何其他对象添加到数组中。当函数返回时,代码将尝试使用对象非常不正确。您几乎肯定会遇到奇怪的行为和/或访问违规。由于 root 问题 已在程序的早期以静默方式引入,因此它们将更难以调试。

结论

虽然该技术有效,但建议您使用TObjectList

  • 这保留了基于标准对象的类型检查。
  • 它支持与数组类似的用途,因此通常是很好的替代品。
  • 此外,容器可以在您添加和删除项目时动态调整大小 - 无需再手动调整大小。
  • 唯一的小不便是您必须创建和销毁TObjectList

即使 TList 通常也是一个更好的选择,但您必须在 Pointer 和类类型之间执行未经检查的强制转换。

【讨论】:

  • 感谢您的解释。在大多数情况下,我仍然更喜欢数组,因为否则我应该在每次使用它们时创建并释放列表和强制转换项。不管怎样,你的回答完全解开了我所有的疑惑!
猜你喜欢
  • 2019-09-14
  • 1970-01-01
  • 2020-02-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-03
  • 2011-04-22
  • 1970-01-01
相关资源
最近更新 更多