Jeroen Pluimers has been blogging about implementing enumerators, which are those things that allow your code to hook into the for-in loop syntax introduced in D2005. His use of the concept so far seems fairly straightforward, but partly because of that, I’m inclined to take issue with this sort of thing:
function TComponentEnumerator.MoveNext: Boolean; begin Assert(FMaxValue = FComponent.ComponentCount - 1, 'ComponentCount changed during enumeration'); // ... end;
OK, I realise the VCL’s default enumerators haven’t been written to expect the enumerated items may change during the enumeration, but why not? Cf. the following, from my Exif library code:
function TExifSection.Enumerator.MoveNext: Boolean;
if (FCurrent <> nil) and (FIndex < FTags.Count) and (FCurrent = FTags.List[FIndex]) then Inc(FIndex); Result := FIndex < FTags.Count; if Result then FCurrent := FTags.List[FIndex]; end; [/sourcecode] The enumerator then has the following constructor (its Current property directly reads the FCurrent field): [sourcecode language='delphi'] constructor TExifSection.Enumerator.Create(ATagList: TList); begin FCurrent := nil; FIndex := 0; FTags := ATagList; end; [/sourcecode] Implementing the enumerator like that allows it to be used like this: [sourcecode language='delphi'] for Tag in ExifData[esDetails] do if Tag.DataType = tdUndefined then Tag.Delete; [/sourcecode] Given it wasn't difficult to add this extra flexibility, where's the benefit in actively going against it...?