1

I have some functions which accepts an array of TObject as a var parameter, for example:

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;

For reusing the same functions, I'm casting several dynamic array of TObject's descendant classes to TObjectArray before passing them to my functions, for example:

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

  //...

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

Is this a safe practice or it could cause some problem that I didn't considered?

7
  • If you cast only TObject-compatible arrays, then it probably will work. But it is awful anyway. Why don't you use generic TList<T>? Commented Mar 20, 2018 at 11:18
  • @AndreiGalatyn: Because I'm using Delphi 2007 Commented Mar 20, 2018 at 11:21
  • You can use regular classes TList / TObjectList. Commented Mar 20, 2018 at 11:22
  • Surely you can do better than this. But yes, that's going to work out. Commented Mar 20, 2018 at 11:44
  • @DavidHeffernan: Could you please explain what you mean? Commented Mar 20, 2018 at 13:28

1 Answer 1

3

The technique itself doesn't cause harm provided the arrays are compatible. The members of an array of TObject are simply references to objects. Since objects can be used safely from an ancestor reference, there is no inherent problem.

Certainly the code you've shown in your question is safe. You could even Free the object instance you're removing/deleting if that makes sense in terms of your ownership pattern.


That said, there is a risk in that the compiler is unable to perform any of its typical type safety checks.

  • In the extreme case, you're able to cast between for example array of Byte and array of TObject
  • More subtly, you can accidentally cast between arrays of incompatible object types (e.g. cast between array of TButton and array of TQuery). When working with individual objects you have the option of a checked type-cast using (<object> as <type>). This performs a compile-time check to verify the types are within the same hierarchy (otherwise cast is guaranteed to be incompatible), and a run-time check to ensure the object instance is actually of the correct type.
  • Although removing and swapping objects in the array is safe, the var reference means you can also add objects to the array. Now whereas an array of TButton forces you to add TButton (or subclass) instances; having typecast to array of TObject means you can accidentally add any other object to the array. And when the function returns, code will attempt use objects very incorrectly. You're almost certain to get strange behaviour and/or access violations. They will be much more difficult to debug due to the root problem having been silently introduced earlier in the program.

Conclusion

While the technique works, you'd be much better advised to use a TObjectList.

  • This retains the standard object based type-checking.
  • It supports similar use to an array, so is usually a great substitute.
  • And as an extra bonus, the container is able dynamically resize as you add and remove items - no more manual resizing required.
  • The only minor inconvenience is that you have to create and destroy the TObjectList.

Even TList would be a generally better choice, though you'd have to perform unchecked casting between Pointer and class types.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for explanation. In most cases, I still prefer arrays because otherwise I should create and free the list and cast items everytime I use them. Anyhow, you're answer has fully clarified all my doubts!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.