1) Does anyone know if it is possible to loop through an irregular enumeration in Delphi (XE)?
Looping over a normal enumeration is ok. From Delphi Basics:
var
suit : (Hearts, Clubs, Diamonds, Spades);
begin
// Loop 3 times
For suit := Hearts to Diamonds do
ShowMessage('Suit = '+IntToStr(Ord(suit)));
end;
But, if 'suit' instead is declared as
var
suit : (Hearts=1, Clubs, Diamonds=10, Spades);
it loops 10 times. Not suprising, but I would like to loop 3. The only solution I've found so far is converting an enumeration to a set and use the 'for ... in'-loop like on delphi.about.com.
So, if answer to question 1) is no, then:
2) How to convert from enumeration to set in Delphi?
The context I am using it in is a component array of edit-boxes (TEdit) that has an irregular numbering (edit1, edit5, edit7, edit3, ...). While it is possible to reorder all the edit-boxes, it removes the reason of using enumeration as a flexible way to allow addition of an edit-box in the middle of the enumeration.
A dirty option, useful for small enumerations:
Works nice in Delphi 2007. Don't know about older versions. Be aware, using
for Suit in [Hearts..Diamonds] do
has the same problem as your loop.Btw, I use
WriteLn()
because I tested this in a console application. :-)I do not have a Delphi compiler at hand right now, but I tink that gabr's approach can be rather significantly improved by doing
Who knows, maybe it doesn't even compile.
Loop using Ord(Hearts) to Ord(Spades) ?
I always use
It should be understood (and often isn't) that the moment you put hard ordinal assignments into an enumeration, it ceases for all intents to be a Pascalian enumerated type - it just becomes a "bag of constants", which is not the same thing. This is what C-programmers call enumerations. However, a Pascalian enumerated type is ORDINAL in all criterion: It has discrete consecutive values that respond meaningfully to the base operations ORD, PRED, SUCC. Enumerations in C don't do this, and neither do enums in Pascal once you force the ordinals apart.
THIS is the reason that Delphi's RTTI basically refuses to return type information once this has been done. To all intents the type is essentially a tkUnknown, and has to be treated as a 'bag' of compile-time constants. It is only because it still plays lip service to being an ordinal and has (sometimes shaky) support for use in sets that people are led into believing it should still behave like a proper enumerated type. It's better to just understand it for what it really is: a nod to enumerated values in C. Avoid mixing the coding metaphor!
If you do this, then your solution becomes obvious: you use an enumerated type (a proper one) to index a corresponding array of CONSTANTS. Then you can make the ordinals whatever you want, and the enums retain their full RTTI definitions as a proper enumeration. So: your ENUMERATED TYPE contains proper unchanged ordinal values. You get your funny numbers by indexing the constants array using the enumeration -ergo array [MyEnums] of byte = (1,3,8,22,99,whatever)