woensdag 21 januari 2009

Delphi Enumerators: "for o in MyObject do"

Ik gebruik Delphi 2007 nog niet zo heel lang, omdat de huidige klant nog de oude Delphi 6 versie gebruikte. Sowieso zijn er best veel bedrijven die bijvoorbeeld Delphi 7 nog steeds gebruiken (wat vaak gewoon goed bevalt). Best jammer, want Delphi 2007 en 2009 zijn mooie en goede Delphi versies, met veel verbeteringen: IDE, VCL en Language features.

Het nadeel van nieuwe features is echter: je moet ze wel gebruiken :-). Heel gauw ben je geneigd om je oude gewoontes te blijven gebruiken: bijvoorbeeld nog steeds "for i := 0 to stringlist.Count-1 do" gebruiken in plaats van "for s in stringlist".

Ik had al eens een serie interessante blogs gelezen over "fun with enumerators":
http://17slon.com/blogs/gabr/2007/03/fun-with-enumerators-part-1.html
http://17slon.com/blogs/gabr/2007/03/fun-with-enumerators-part-2-multiple.html
http://17slon.com/blogs/gabr/2007/03/fun-with-enumerators-part-3.html
http://17slon.com/blogs/gabr/2007/03/fun-with-enumerators-part-4-external.html
http://17slon.com/blogs/gabr/2007/03/fun-with-enumerators-part-5-class.html

In feite komt het erop neer, dat elke class die een "public GetEnumerator" functie heeft, gebruikt kan worden voor een "for in" loop.
De GetEnumerator functie moet een class teruggeven met de volgende functies (als voorbeeld van TStringList.GetEnumerator):
TStringsEnumerator = class
public
function GetCurrent: string;
function MoveNext: Boolean;
property Current: string read GetCurrent;
end;
Van de volgende code...:
for s in stringlist do
ShowMessage(s);
...maakt Delphi onderwater de volgende code ervan:
enumerator := stringlist.GetEnumerator;
while enumerator.MoveNext do
begin
s := enumerator.Current;
ShowMessage(s);
end;
enumerator.Free;
Je kunt dus ook zelf eenvoudig aan een eigen class deze handige enumerator functionaliteit toevoegen! Of via "class helpers" aan een bestaande class.

Op een gegeven moment was ik het namelijk zat om steeds "for i to count-1" te gebruiken, en toen moest ik weer denken aan de eerder genoemde blogs. Met de bovenstaande code kon ik zelf een veelgebruikte class even uitbreiden met enumerators :-).

Trouwens, "for in" kun je ook gebruiken met arrays en sets:
var i:integer;
c: char;
begin
for i in intergerarray do ;
for c in teststring do ;
end;

Geen opmerkingen: