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.
Viser innlegg med etiketten Record. Vis alle innlegg
Viser innlegg med etiketten Record. Vis alle innlegg

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!