This code is very dangerous. Destroying objects not from the end of the list.
And also, Items.Delete automatically updates all the elements of the associated RadioGroup: removes unnecessary ones, adds the necessary ones.
Sorry, I don't understand: nothing is destroyed here; the code is a reaction on the user destroying some item, of course, not necessarily at the end of the list.
I do agree, though, that having Items.Delete() here causes a lot of trouble, in particular when the similar case with TCheckGroup is considered - see my bugreport
https://gitlab.com/freepascal.org/lazarus/lazarus/-/issues/40261. So far, i could not create a solution for this issue without side-effects. Least side-effects are when the deleted FButtonList is set to nil in the Notification procedure (plus adding some nil checks in the component code), but this way still the FButtonList is not in sync with the Items.
procedure TCustomRadioGroup.Notification(AComponent: TComponent; Operation: TOperation);
var
i: Integer;
begin
inherited Notification(AComponent, Operation);
if (Operation = opRemove) then
for i := 0 to FButtonList.Count-1 do
if AComponent = TComponent(FButtonList[i]) then
begin
FButtonList[i] := nil;
exit;
end;
end;