arrays - 在将动态数组作为变量参数传递之前是否可以强制转换?

标签 arrays delphi casting dynamic-arrays delphi-2007

我有一些函数可以接受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;


这是安全的做法,还是可能引起我没有考虑的问题?

最佳答案

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

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



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


在极端情况下,您可以在array of Bytearray of TObject之间进行转换
更巧妙地,您可能会意外地在不兼容的对象类型的数组之间进行转换(例如,在array of TButtonarray of TQuery之间进行转换)。使用单个对象时,可以选择使用(<object> as <type>)进行选中的类型转换。这将执行编译时检查,以验证类型是否在同一层次结构中(否则,强制转换是不兼容的),并执行运行时检查以确保对象实例实际上是正确的类型。
尽管删除和交换数组中的对象是安全的,但var引用意味着您还可以将对象添加到数组中。现在,array of TButton会强制您添加TButton(或子类)实例;将类型转换为array of TObject意味着您可以不小心将任何其他对象添加到数组。当函数返回时,代码将尝试非常错误地使用对象。您几乎肯定会遇到奇怪的行为和/或访问冲突。由于根问题已在程序的较早版本中无声引入,因此调试起来将更加困难。




结论

尽管该技术有效,但最好还是建议您使用TObjectList


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


尽管您必须在TList和类类型之间执行未经检查的强制转换,甚至Pointer还是通常更好的选择。

关于arrays - 在将动态数组作为变量参数传递之前是否可以强制转换?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49382574/

相关文章:

delphi - 找不到用于拆分 Longint 的搜索词

delphi - 应用程序有时会从 Win7 的 ALT-TAB 列表中消失

c# - 无法将 Action<object, EventArgs> 转换为 EventHandler?

javascript - 如果我分块循环遍历一个大数组,它会提高性能吗?

delphi - 如何在其他组件后面显示视频?

Java - 如何转义打印控制字符?

c# - 在 C# 中将泛型对象转换回原始对象

javascript - 按键/值合并对象数组

arrays - Excel VBA(不是 VBScript)101 : How do I create and read a multidimensional array?

javascript - 如何修复 "Uncaught TypeError: Cannot read property ' number' of undefined”?