- changed status to resolved
calling clear on a set will generate an OnChange event in which you can't call ToArray()
Issue #399
resolved
See below code snippet, the call to ToArray() in the OnSetChanged event handler throws an range check error after the call to s.Clear()
procedure TForm3.FormCreate(Sender: TObject);
begin
var s := TCollections.CreateSet<string>();
s.OnChanged.Add(OnSetChanged);
s.Add('a');
s.Add('b');
s.Clear();
end;
procedure TForm3.OnSetChanged(Sender: TObject; const Item: string; Action: TCollectionChangedAction);
begin
var b := TFoldedHashSet<string>(Sender).ToArray;
end;
It seems to be due to fHastTable.ClearCount (line 8) from this snippet from Spring.Collection.Sets
procedure THashSet<T>.Clear;
var
item: PItem;
i: Integer;
begin
if Assigned(Notify) then
begin
fHashTable.ClearCount;
item := PItem(fHashTable.Items);
for i := 1 to fHashTable.ItemCount do //FI:W528
if item.HashCode >= 0 then
Notify(Self, item.Item, caRemoved);
end;
fHashTable.Clear;
end;
It shows up in different forms, if I change the event handler from the original snippet to (add .Ordered)
procedure TForm3.OnSetChanged(Sender: TObject; const Item: string; Action: TCollectionChangedAction);
begin
var b := TFoldedHashSet<string>(Sender).Ordered.ToArray;
end;
It breaks on line 10 in this snippet from Spring.Collections.Sets (fHashTable.Count is 0, thus Length(Result) = 0, thus you can’t target Result[targetIndex] on line 10).
function THashSet<T>.ToArray: TArray<T>;
var
sourceIndex, targetIndex: Integer;
begin
SetLength(Result, fHashTable.Count);
targetIndex := 0;
for sourceIndex := 0 to fHashTable.ItemCount - 1 do
if TItems(fHashTable.Items)[sourceIndex].HashCode >= 0 then
begin
Result[targetIndex] := TItems(fHashTable.Items)[sourceIndex].Item;
Inc(targetIndex);
end;
end;
Comments (2)
-
repo owner -
repo owner fixed
#399→ <<cset da80e4e91442>>
- Log in to comment
fixed
#399→ <<cset 84bab3ed0131>>