test

progging - To wander about and beg; to seek food or other supplies by low arts; to seek for advantage by mean shift or tricks.
progging - Programmer slang for writing computer code.

fredag 19. august 2011

Implementing enumerators on delphi records

Implementing enumerators are pretty easy in Delphi and many articles exist on the topic:

http://hallvards.blogspot.com/2007/10/more-fun-with-enumerators.html
http://www.thedelphigeek.com/2007/03/fun-with-enumerators.html

For some reason, I had a simple record to hold a small array of another type where the use was to loop round and do some action on every type. I used a record instead of a class to avoid the Create/Destroy and since it was just used to hold some simple data.
The first thing I noticed was that the Enumerator had to be a class (and not a record as recommended here) because I could not have a forward declaration to a record. Since my "list type" was a record I had to "forward declare" the enumerator before the record type.

  TLongTrendFieldsEnumerator = class;

  TLongTrendFields = record
  private
    { Private declarations }
    PlotList: array[0..MAX_LONG_TREND_FIELDS] of TPlot;
    function GetItem(index : Integer) : TPlot;
  public
    { Public declarations }
    property Items[i:Integer] : TPlot read GetItem; default;
    function GetEnumerator: TLongTrendFieldsEnumerator;
  end;

The next thing to think of is that the list type is a record, so we don't want to copy the instance when we pass it to the enumerator. So we use pointer instead, beginning with declaring a pointer type

  TLongTrendFieldsEnumerator = class;

  TLongTrendFieldsPointer = ^TLongTrendFields;
  TLongTrendFields = record
  private
  ...
So then the enumerator class will look like this:


  TLongTrendFieldsEnumerator = class
  private
    index: Integer;
    fields: TLongTrendFieldsPointer;
  public
    constructor Create(aFields: TLongTrendFieldsPointer);
    function MoveNext: Boolean;
    function GetCurrent: TPlot;
    property Current: TPlot read GetCurrent;
  end;  
The only difference in the implementation is that when the list type creates the enumerator it has to send a reference/pointer to the enumerator's constructor.
function TLongTrendFields.GetEnumerator: TLongTrendFieldsEnumerator;
begin
  Result := TLongTrendFieldsEnumerator.Create(@Self);
end;
The rest of the implementation is identical to the other examples (without pointers) thanks to Delphi's nice pointer syntax handling!

Ingen kommentarer:

Legg inn en kommentar