Skip to content

Commit dd0d0fb

Browse files
committed
optimized TEnumerableBase methods
1 parent cfa6fb0 commit dd0d0fb

File tree

1 file changed

+51
-46
lines changed

1 file changed

+51
-46
lines changed

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

Lines changed: 51 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1253,22 +1253,28 @@ function TEnumerableBase<T>.Single: T;
12531253
function TEnumerableBase<T>.Single(const predicate: Predicate<T>): T;
12541254
var
12551255
enumerator: IEnumerator<T>;
1256+
item: T;
1257+
found: Boolean;
12561258
begin
12571259
if not Assigned(predicate) then RaiseHelper.ArgumentNil(ExceptionArgument.predicate);
12581260

1261+
found := False;
12591262
enumerator := IEnumerable<T>(this).GetEnumerator;
1260-
while enumerator.MoveNext do
1263+
while True do
12611264
begin
1262-
Result := enumerator.Current;
1263-
if predicate(Result) then
1265+
if not enumerator.MoveNext then Break;
1266+
item := enumerator.Current;
1267+
if predicate(item) then
12641268
begin
1265-
while enumerator.MoveNext do
1266-
if predicate(enumerator.Current) then
1267-
RaiseHelper.MoreThanOneMatch;
1268-
Exit;
1269+
found := not found;
1270+
if found then
1271+
Result := item
1272+
else
1273+
RaiseHelper.MoreThanOneMatch;
12691274
end;
12701275
end;
1271-
RaiseHelper.NoMatch;
1276+
if not found then
1277+
RaiseHelper.NoMatch;
12721278
end;
12731279

12741280
function TEnumerableBase<T>.SingleOrDefault: T;
@@ -1299,26 +1305,31 @@ function TEnumerableBase<T>.SingleOrDefault(const predicate: Predicate<T>): T;
12991305
Result := IEnumerable<T>(this).SingleOrDefault(predicate, defaultValue);
13001306
end;
13011307

1302-
function TEnumerableBase<T>.SingleOrDefault(const predicate: Predicate<T>;
1303-
const defaultValue: T): T;
1308+
function TEnumerableBase<T>.SingleOrDefault(const predicate: Predicate<T>; const defaultValue: T): T;
13041309
var
13051310
enumerator: IEnumerator<T>;
1311+
item: T;
1312+
found: Boolean;
13061313
begin
13071314
if not Assigned(predicate) then RaiseHelper.ArgumentNil(ExceptionArgument.predicate);
13081315

1316+
found := False;
13091317
enumerator := IEnumerable<T>(this).GetEnumerator;
1310-
while enumerator.MoveNext do
1318+
while True do
13111319
begin
1312-
Result := enumerator.Current;
1313-
if predicate(Result) then
1320+
if not enumerator.MoveNext then Break;
1321+
item := enumerator.Current;
1322+
if predicate(item) then
13141323
begin
1315-
while enumerator.MoveNext do
1316-
if predicate(enumerator.Current) then
1317-
RaiseHelper.MoreThanOneMatch;
1318-
Exit;
1324+
found := not found;
1325+
if found then
1326+
Result := item
1327+
else
1328+
RaiseHelper.MoreThanOneMatch;
13191329
end;
13201330
end;
1321-
Result := defaultValue;
1331+
if not found then
1332+
Result := defaultValue;
13221333
end;
13231334

13241335
function TEnumerableBase<T>.Skip(count: Integer): IEnumerable<T>;
@@ -1393,52 +1404,46 @@ function TEnumerableBase<T>.TakeWhile(
13931404

13941405
function TEnumerableBase<T>.ToArray: TArray<T>;
13951406
var
1396-
intf: IInterface;
1397-
count: Integer;
1407+
enumerator: IEnumerator<T>;
1408+
count, capacity: Integer;
13981409
begin
13991410
Result := nil;
1400-
if GetInterface(IReadOnlyCollectionOfTGuid, Pointer(intf)) then
1401-
begin
1402-
count := IReadOnlyCollection<T>(intf).Count;
1403-
if count > 0 then
1404-
begin
1405-
SetLength(Result, count);
1406-
IReadOnlyCollection<T>(intf).CopyTo(Result, 0);
1407-
end;
1408-
end
1409-
else
1411+
count := 0;
1412+
capacity := 0;
1413+
enumerator := IEnumerable<T>(this).GetEnumerator;
1414+
while enumerator.MoveNext do
14101415
begin
1411-
count := 0;
1412-
intf := IEnumerable<T>(this).GetEnumerator;
1413-
while IEnumerator<T>(intf).MoveNext do
1416+
if count >= capacity then
14141417
begin
1415-
if Result = nil then
1416-
SetLength(Result, 4)
1417-
else if DynArrayLength(Result) = count then
1418-
SetLength(Result, count * 2);
1419-
Result[count] := IEnumerator<T>(intf).Current;
1420-
Inc(count);
1418+
capacity := GrowCapacity(capacity);
1419+
SetLength(Result, capacity);
14211420
end;
1422-
SetLength(Result, count);
1421+
Result[count] := enumerator.Current;
1422+
Inc(count);
14231423
end;
1424+
SetLength(Result, count);
14241425
end;
14251426

14261427
function TEnumerableBase<T>.TryGetElementAt(var value: T; index: Integer): Boolean;
14271428
var
14281429
enumerator: IEnumerator<T>;
14291430
begin
1430-
if index < 0 then
1431-
Exit(False);
1432-
enumerator := IEnumerable<T>(this).GetEnumerator;
1433-
while enumerator.MoveNext do
1431+
if index >= 0 then
14341432
begin
1435-
if index = 0 then
1433+
enumerator := IEnumerable<T>(this).GetEnumerator;
1434+
while True do
14361435
begin
1436+
if not enumerator.MoveNext then
1437+
Break;
1438+
Dec(index);
1439+
if index >= 0 then
1440+
Continue;
1441+
14371442
value := enumerator.Current;
14381443
Exit(True);
14391444
end;
1440-
Dec(index);
14411445
end;
1446+
value := Default(T);
14421447
Result := False;
14431448
end;
14441449

0 commit comments

Comments
 (0)