Question

Je souhaite parcourir les éléments d'une énumération.

J'aimerais pouvoir dire quelque chose comme ceci:

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;

Voici ce que j'ai pu voir de plus près:

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;

Ce que j'utilise comme ceci:

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;

Cela fonctionne bien, sauf que la liste que je reçois ressemble à ceci (remarquez les deux derniers éléments):

wdMonday
wdTuesday
wdWednesday
wdThursday
wdFriday
Unit1
'@'#0'ôÑE'#0#0#0#0#0#0#0#0#0#0#0#0#0  <more garbage characters>

Les deux éléments à la fin ne sont évidemment pas ce que je veux.

Existe-t-il un meilleur moyen de parcourir les éléments d'un type énuméré?

Si ce n'est pas le cas, est-il prudent de supposer que toujours seront exactement deux éléments supplémentaires utilisant ma méthode actuelle? Il est évident que l’un est le nom de l’unité ... mais quel est le "@"? symbole faisant? Est-ce vraiment une foutaise, ou est-ce plus d'informations de type?

J'utilise Delphi 2007. Merci pour vos idées.

Était-ce utile?

La solution

Simple:

type
  TWeekdays = (wdMonday, wdTuesday, wdWednesday, wdThursday, wdFriday);

procedure Test;
var
  el: TWeekdays;
begin
  for el := Low(TWeekdays) to High(TWeekdays) do
    ; //
end;

Autres conseils

C’est beaucoup plus complexe que cela, lorsqu’on utilise des énumérations spéciales ... voyons une solution qui fonctionne vraiment à 100% pour une définition énumérée complexe:

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:

  • Toutes les définitions énumérées ne doivent pas nécessairement commencer par 0 et être contiguës; elles peuvent être définies comme dans l'exemple
  • Voir comment le type a été défini (pas trié, pas contigu, etc ...)
  • Voir comment il a été ajouté un tableau constant avec le bon ordre des éléments
  • Doit itérer sur un tel tableau car l'ordre est perdu et Succ et Pred ne fonctionnent pas correctement avec ce type d'énumérations

Pourquoi cela a-t-il été fait comme ça?:

  • L'ordre énuméré doit être conservé et il n'est pas contigu
  • Delphi, quand sur cet exemple crée le type TmyEnumType , lui assigne (9-2 + 1 = 8) des éléments (du plus bas (2) au plus élevé (9), ainsi les valeurs valides pour ce type les types vont de l'ordinal 2 à l'ordinal 9
  • Les fonctions Delphi Succ et Pred n'augmentent et ne décroissent que d'une unité; ne recherchez pas de manière non-contiguë de la définir. Attribuez donc des valeurs hors de la portée et perdez également l'ordre de définition

Le tour:

  • Déclarer un tableau constant contigu avec des éléments dans le bon ordre
  • Boucle sur ce tableau constant

Si vous essayez cet autre moyen de penser (logique), cela ne fonctionnera pas (peu importe si vous l'utilisez pour boucle, boucle en boucle, répétez jusqu'à ce que, 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

C’est ce que j’ai testé par moi-même sur Turbo Delphi 2006.

Vous pouvez utiliser Succ (x) et Pred (x) pour parcourir une énumération en boucle. Mais souvenez-vous de vérifier les limites pour ne pas essayer Succ (x) sur le dernier élément de l'énumération!

Exemple:

type
  TWeekdays = (wdMonday, wdTuesday, wdWednesday, wdThursday, wdFriday);

procedure Test;
var
  val: TWeekdays;
begin
  val := wdTuesday;
  val := Succ(val); // wdWednesday

  val := wdFriday;
  val := Pred(val); // wdThursday, 
end;

J'ai créé un EnumerationEnumerator afin que vous puissiez l'utiliser dans l'instruction 'for ... in' de Delphi. Cependant, à l’époque, cela engendrait parfois des erreurs de compilation internes.

Modifier:

Si vous avez réussi à le faire fonctionner dans Delphi 2007 et versions ultérieures, voir cet article de blog (et la discussion assez intéressante qui s’y rapporte).

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top