Skip to content

Commit 368bbe9

Browse files
committed
fixed a bug with CopyTo and added optimizations to TList<T> constructors
1 parent 90d4c65 commit 368bbe9

File tree

3 files changed

+61
-3
lines changed

3 files changed

+61
-3
lines changed

Source/Base/Collections/Spring.Collections.Base.pas

+2-2
Original file line numberDiff line numberDiff line change
@@ -219,8 +219,8 @@ TCollectionBase<T> = class abstract(TEnumerableBase<T>, ICollection<T>, IReadO
219219
procedure Changed(const item: T; action: TCollectionChangedAction); virtual;
220220
public
221221
constructor Create; override;
222-
constructor Create(const collection: array of T); overload;
223-
constructor Create(const collection: IEnumerable<T>); overload;
222+
constructor Create(const collection: array of T); overload; virtual;
223+
constructor Create(const collection: IEnumerable<T>); overload; virtual;
224224

225225
procedure Add(const item: T);
226226
procedure AddRange(const collection: array of T); overload; virtual;

Source/Base/Collections/Spring.Collections.Lists.pas

+41-1
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,8 @@ TEnumerator = class(TEnumeratorBase<T>)
9898
function EnsureCapacity(value: Integer): Integer;
9999
public
100100
constructor Create; override;
101+
constructor Create(const collection: array of T); override;
102+
constructor Create(const collection: IEnumerable<T>); override;
101103
destructor Destroy; override;
102104

103105
function GetEnumerator: IEnumerator<T>; override;
@@ -268,6 +270,38 @@ constructor TList<T>.Create;
268270
fArrayManager := TMoveArrayManager<T>.Create;
269271
end;
270272

273+
constructor TList<T>.Create(const collection: array of T);
274+
var
275+
i: Integer;
276+
begin
277+
Create;
278+
fCount := Length(collection);
279+
if fCount > 0 then
280+
begin
281+
SetLength(fItems, fCount);
282+
for i := Low(collection) to High(collection) do
283+
fItems[i] := collection[i];
284+
end;
285+
end;
286+
287+
constructor TList<T>.Create(const collection: IEnumerable<T>);
288+
var
289+
c: ICollection<T>;
290+
begin
291+
if Supports(collection, ICollection<T>, c) then
292+
begin
293+
Create;
294+
fCount := c.Count;
295+
if fCount > 0 then
296+
begin
297+
SetLength(fItems, fCount);
298+
c.CopyTo(fItems, 0);
299+
end;
300+
end
301+
else
302+
inherited;
303+
end;
304+
271305
destructor TList<T>.Destroy;
272306
begin
273307
inherited Destroy;
@@ -568,12 +602,18 @@ function TList<T>.Contains(const value: T;
568602
end;
569603

570604
procedure TList<T>.CopyTo(var values: TArray<T>; index: Integer);
605+
var
606+
i: Integer;
571607
begin
572608
{$IFDEF SPRING_ENABLE_GUARD}
573609
Guard.CheckRange(Length(values), index, fCount);
574610
{$ENDIF}
575611

576-
fArrayManager.Move(fItems, TArrayOfT(values), 0, index, fCount);
612+
for i := 0 to fCount - 1 do
613+
begin
614+
values[index] := fItems[i];
615+
Inc(index);
616+
end;
577617
end;
578618

579619
function TList<T>.ToArray: TArray<T>;

Tests/Source/Base/Spring.Tests.Collections.pas

+18
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,7 @@ TTestInterfaceList = class(TTestCase)
322322
published
323323
procedure TestInterfaceListCreate;
324324
procedure TestGetElementType;
325+
procedure TestCopyTo;
325326
end;
326327

327328
TMyCollectionItem = class(TCollectionItem);
@@ -1885,6 +1886,23 @@ procedure TTestInterfaceList.SetUp;
18851886
SUT := TInterfaceList<IInvokable>.Create as IList<IInvokable>;
18861887
end;
18871888

1889+
type
1890+
TInvokable = class(TInterfacedObject, IInvokable);
1891+
1892+
procedure TTestInterfaceList.TestCopyTo;
1893+
var
1894+
values: TArray<IInvokable>;
1895+
i: Integer;
1896+
begin
1897+
for i := 0 to MaxItems - 1 do
1898+
SUT.Add(IInvokable(TInvokable.Create));
1899+
SetLength(values, MaxItems);
1900+
SUT.CopyTo(values, 0);
1901+
CheckEquals(MaxItems, Length(values));
1902+
CheckSame(SUT.First, values[0]);
1903+
CheckSame(SUT.Last, values[MaxItems-1]);
1904+
end;
1905+
18881906
procedure TTestInterfaceList.TestGetElementType;
18891907
begin
18901908
Check(TypeInfo(IInvokable) = SUT.ElementType);

0 commit comments

Comments
 (0)