I want to iterate through the items in an enumeration.
I'd like to be able to say something like this:
type TWeekdays = (wdMonday, wdTuesday, wdWednesday, wdThursday, wdFriday); ... elementCount := GetElementCount(TypeInfo(TWeekDays)); for i := 0 to elementCount - 1 do begin ShowMessage(GetEnumName(TypeInfo(TWeekdays),i)); end;
The closest I've been able to come is this:
function MaxEnum(EnumInfo: PTypeInfo): integer; const c_MaxInt = 9999999; var i: integer; s: string; begin //get # of enum elements by looping thru the names //until we get to the end. for i := 0 to c_MaxInt do begin s := Trim(GetEnumName(EnumInfo,i)); if 0 = Length(s) then begin Result := i-1; Break; end; end; end;
Which I use like this:
procedure TForm1.BitBtn1Click(Sender: TObject); var i, nMax: integer; begin ListBox1.Clear; nMax := MaxEnum(TypeInfo(TWeekdays)); for i := 0 to nMax do begin ListBox1.Items.Add(GetEnumName(TypeInfo(TWeekdays),i)); end; end;
That works well, except the list I get looks like this (notice the last two items):
wdMonday wdTuesday wdWednesday wdThursday wdFriday Unit1 '@'#0'ôÑE'#0#0#0#0#0#0#0#0#0#0#0#0#0 <more garbage characters>
The two items at the end are obviously not what I want.
Is there a better way to iterate through the elements of an enumerated type?
If not, then is it safe to assume that there will always be exactly two extra items using my current method? Obviously one is the Unit name... but what is the "@" symbol doing? Is it really garbage, or is it more type information?
I'm using Delphi 2007. Thanks for any insights.
To iterate through an enumeration, you can move it into an array using the GetValues method. You could also iterate through an enumeration using a For... Each statement, using the GetNames or GetValues method to extract the string or numeric value.
Enums don't have methods for iteration, like forEach() or iterator(). Instead, we can use the array of the Enum values returned by the values() method.
you can iterate the elements like: for(int i=Bar; i<=Last; i++) { ... } Note that this exposes the really-just-an-int nature of a C enum. In particular, you can see that a C enum doesn't really provide type safety, as you can use an int in place of an enum value and vice versa.
Use the Object. keys() or Object. values() methods to get an array of the enum's keys or values.
Simple:
type TWeekdays = (wdMonday, wdTuesday, wdWednesday, wdThursday, wdFriday); procedure Test; var el: TWeekdays; begin for el := Low(TWeekdays) to High(TWeekdays) do ; // end;
It is quite more complex than that, when used special enumerations... let's see a really 100% working solution for a complex enumerated definition:
type TmyEnumType=(myEnumTypeA=5,myEnumTypeB=2,myEnumTypeC=9); const myEnumTypeOrder:Array[1..3] of TmyEnumType=(myEnumTypeA,myEnumTypeB,myEnumTypeC); procedure TForm1.Button1Click(Sender: TObject); var myEnumTypeVariable:TmyEnumType; begin myEnumTypeVariable:=Low(TmyEnumType); for myEnumTypeVariable in myEnumTypeOrder do begin ShowMessage(IntToStr(Ord(myEnumTypeVariable))); // Sample code to show enum integer value // Extra code you neede end; end; // This code shows three messages in this secuence: 5, 2, 9 // Correct number of elements and in the correct order
Notes:
Why it has been done like that?:
TmyEnumType
assign to it (9-2+1=8) elemments (from lower one (2) to higher one (9), so valid values for such type are from ordinal 2 to ordinal 9The Trick:
If you try this other (logical human way of thinking) it will not work (no matter if use for loop, while loop, repeat until, etc):
type TmyEnumType=(myEnumTypeA=5,myEnumTypeB=2,myEnumTypeC=9); procedure TForm1.Button1Click(Sender: TObject); var myEnumTypeVariable:TmyEnumType; begin for myEnumTypeVariable:=Low(TmyEnumType) to High(TmyEnumType); do begin ShowMessage(IntToStr(Ord(myEnumTypeVariable))); // Sample code to show enum integer value // Extra code you neede end; end; // This code shows eight messages in this secuence: 2, 3, 4, 5, 6, 7, 8, 9 // Inorrect number of elements and in order is lost
That is what i have tested by my own on Turbo Delphi 2006.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With