@@ -506,13 +506,19 @@ TInnerCollection<T> = class sealed(TEnumerableBase<T>,
506506 private type
507507 { $REGION 'Nested Types'}
508508 PT = ^T;
509- TEnumerator = class (THashTableEnumerator, IEnumerator<T>)
510- private
509+ PEnumerator = ^TEnumerator;
510+ TEnumerator = record
511+ Vtable: Pointer;
512+ RefCount: Integer;
513+ TypeInfo: PTypeInfo;
514+ Parent: TRefCountedObject;
515+ fSource: TInnerCollection<T>;
516+ fIndex: Integer;
517+ fVersion: Integer;
511518 fCurrent: T;
512519 function GetCurrent : T;
513- public
514- procedure BeforeDestruction ; override;
515520 function MoveNext : Boolean;
521+ class var Enumerator_Vtable: TEnumeratorVtable;
516522 end ;
517523 { $ENDREGION}
518524 private
@@ -791,7 +797,8 @@ function TEnumeratorBlock._Release: Integer;
791797 Result := AtomicDecrement(RefCount);
792798 if Result = 0 then
793799 begin
794- Parent._Release;
800+ if Assigned(Parent) then
801+ Parent._Release;
795802 FinalizeRecord(@Self, TypeInfo);
796803 FreeMem(@Self);
797804 end ;
@@ -2166,15 +2173,15 @@ function TInnerCollection<T>.GetElementType: PTypeInfo;
21662173end ;
21672174
21682175function TInnerCollection <T>.GetEnumerator: IEnumerator<T>;
2169- var
2170- enumerator: TEnumerator;
21712176begin
21722177 _AddRef;
2173- enumerator := TEnumerator.Create;
2174- enumerator.fSource := Self;
2175- enumerator.fHashTable := fHashTable;
2176- enumerator.fVersion := enumerator.fHashTable.Version;
2177- Result := enumerator;
2178+ with PEnumerator(TEnumeratorBlock.Create(@Result, @TEnumerator.Enumerator_Vtable,
2179+ TypeInfo(TEnumerator), @TEnumerator.GetCurrent, @TEnumerator.MoveNext))^ do
2180+ begin
2181+ Parent := Self.fSource;
2182+ fSource := Self;
2183+ fVersion := Self.fHashTable.Version;
2184+ end ;
21782185end ;
21792186
21802187function TInnerCollection <T>.GetIsEmpty: Boolean;
@@ -2234,24 +2241,38 @@ function TInnerCollection<T>._Release: Integer;
22342241
22352242{ $REGION 'TInnerCollection<T>.TEnumerator'}
22362243
2237- procedure TInnerCollection <T>.TEnumerator.BeforeDestruction;
2238- begin
2239- TInnerCollection<T>(fSource)._Release;
2240- end ;
2241-
22422244function TInnerCollection <T>.TEnumerator.GetCurrent: T;
22432245begin
22442246 Result := fCurrent;
22452247end ;
22462248
22472249function TInnerCollection <T>.TEnumerator.MoveNext: Boolean;
2250+ var
2251+ hashTable: PHashTable;
2252+ item: PByte;
2253+ offset: Integer;
22482254begin
2249- if inherited MoveNext then
2255+ offset := fSource.fOffset;
2256+ hashTable := fSource.fHashTable;
2257+ if fVersion = hashTable.Version then
22502258 begin
2251- fCurrent := PT(fItem + TInnerCollection<T>(fSource).fOffset)^;
2252- Exit(True);
2253- end ;
2254- Result := False;
2259+ repeat
2260+ if fIndex >= hashTable.ItemCount then
2261+ Break;
2262+
2263+ item := @hashTable.Items[fIndex * hashTable.ItemSize];
2264+ Inc(fIndex);
2265+ if PInteger(item)^ >= 0 then
2266+ begin
2267+ fCurrent := PT(item + offset)^;
2268+ Exit(True);
2269+ end ;
2270+ until False;
2271+ fCurrent := Default(T);
2272+ Result := False;
2273+ end
2274+ else
2275+ Result := RaiseHelper.EnumFailedVersion;
22552276end ;
22562277
22572278{ $ENDREGION}
0 commit comments