Loop through irregular enumeration in Delphi

本小妞迷上赌 提交于 2019-12-19 06:18:25

问题


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.


回答1:


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

type
  TSuit = (Hearts = 1, Clubs, Diamonds = 10, Spades);

const
  Suits: array[0..3] of TSuit = (Hearts, Clubs, Diamonds, Spades);

Who knows, maybe it doesn't even compile.




回答2:


type
  TSuit = (Hearts=1, Clubs, Diamonds=10, Spades);

var
  suit: TSuit;
  suitEnum: array [1..4] of TSuit;

//initialization
suitEnum[1] := Hearts;
suitEnum[2] := Clubs;
suitEnum[3] := Diamonds;
suitEnum[4] := Spades;

for suit in suitEnum do
  DoSomething(suit);



回答3:


I always use

var
  s: TSuit;
begin
  for s := Low(TSuit) to High(TSuit) do
    {something};
end;



回答4:


Loop using Ord(Hearts) to Ord(Spades) ?




回答5:


A dirty option, useful for small enumerations:

type
  TSuit = (Hearts = 1, Clubs, Diamonds = 10, Spades);
var
  Suit: TSuit;
begin
  for Suit in [Hearts, Clubs, Diamonds] do
    WriteLn(Ord(Suit));

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. :-)




回答6:


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)



来源:https://stackoverflow.com/questions/4132717/loop-through-irregular-enumeration-in-delphi

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!