我有一些函数接受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;
这是一种安全的做法,还是会引起一些我没有考虑过的问题?
答案 0 :(得分:3)
如果阵列兼容,该技术本身不会造成伤害。 array of TObject
的成员只是对象的引用。由于可以从祖先引用中安全地使用对象,因此没有固有的问题。
当然,您在问题中显示的代码是安全的。如果在您的所有权模式方面有意义,您甚至可以Free
删除/删除的对象实例。
也就是说,存在编译器无法执行任何典型类型安全检查的风险。
array of Byte
和array of TObject
array of TButton
和array of TQuery
之间投射)。使用单个对象时,您可以选择使用(<object> as <type>)
进行检查类型转换。这将执行编译时检查以验证类型是否在同一层次结构中(否则保证转换不兼容),并执行运行时检查以确保对象实例实际上具有正确的类型。var
引用意味着您还可以将对象添加到数组中。现在,array of TButton
强制您添加TButton
(或子类)实例;将类型转换为array of TObject
意味着您可能会意外地将任何其他对象添加到数组中。当函数返回时,代码将尝试非常错误地使用对象。您几乎肯定会遇到奇怪的行为和/或访问违规行为。由于 root问题已在程序早期默默引入,因此调试起来会更加困难。虽然该技术有效,但建议您使用TObjectList
。
TObjectList
。 即使TList
通常是更好的选择,但您必须在Pointer
和类类型之间执行未经检查的投射。