2010-11-09 4 views
6

1) Weiß jemand, ob es möglich ist, eine unregelmäßige Aufzählung in Delphi (XE) zu durchlaufen?Schleife durch unregelmäßige Aufzählung in Delphi

Schleifen über eine normale Aufzählung ist in Ordnung. Von Delphi Basics:

var 
    suit : (Hearts, Clubs, Diamonds, Spades); 
begin 
// Loop 3 times 
For suit := Hearts to Diamonds do 
    ShowMessage('Suit = '+IntToStr(Ord(suit))); 
end; 

Aber wenn 'Anzug' statt als

var 
    suit : (Hearts=1, Clubs, Diamonds=10, Spades); 

erklärt Schleifen es 10-mal. Nicht überraschend, aber ich würde gerne eine Schleife 3 machen. Die einzige Lösung, die ich bisher gefunden habe, besteht darin, eine Aufzählung in eine Menge umzuwandeln und die 'for ... in'-Schleife wie auf delphi.about.com zu verwenden.

Also, wenn Antwort auf Frage 1) ist nein, dann:
2) Wie von Aufzählung in Delphi zu konvertieren?

Der Kontext, in dem ich es verwende, ist ein Komponenten-Array von Edit-Boxen (TEdit), das eine unregelmäßige Nummerierung hat (edit1, edit5, edit7, edit3, ...). Obwohl es möglich ist, alle Editierfelder neu anzuordnen, wird der Grund für die Verwendung der Aufzählung als flexible Möglichkeit zum Hinzufügen eines Bearbeitungsfelds in der Mitte der Aufzählung entfernt.

+0

Warum können Sie nicht einige "TList" Nachkommen und verwenden darüber iterieren? –

+0

Die Enumeration wird als ein Index in Arrays von TLabels, TEdits und Strings verwendet, so dass ich StringArray [Job]: = Editbox [Job] verwenden kann. TList könnte funktionieren, aber das Ziel war es, den Quellcode leichter lesbar zu machen, indem (unregelmäßige) Enums als Indizes verwendet wurden - wie HashMap in Java. Was ich jetzt sehe, wird wahrscheinlich nicht funktionieren ... – Truls

+0

Haben Sie versucht, XEs RTTI zu verwenden? Das gewöhnliche RTTI vom Gerät 'TypInfo' schlägt kläglich fehl. Anscheinend können Sie nicht 'TypeInfo()' auf einer unregelmäßigen Aufzählung erhalten, ich versuchte auch mit einem Satz und gab mir Zugriffsverletzungen. –

Antwort

7

Ich habe keine Delphi-Compiler zur Hand gerade jetzt, aber ich tink dass gabr Ansatz eher deutlich, indem Sie verbessert werden kann

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

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

Wer weiß, vielleicht ist es gar nicht kompilieren.

+0

Sollte definitiv funktionieren. – gabr

+0

Getestet das und es funktioniert! Vielen Dank. Wenn jemand weiß, ob es möglich ist, die Wiederholung der Aufzählungsliste zu vermeiden, würde ich mich freuen zu wissen. – Truls

0

Schleife mit Ord (Hearts) zu Ord (Spades)?

+2

Ich denke, Ord (Hearts) zu Ord (Spades) wird 11-mal Schleife, und nicht 3, wie ich will. – Truls

3
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); 
+0

Danke für den Vorschlag. Da ich ungefähr 30 Elemente in meinem Enum habe, hatte ich gehofft, manuelle Initialisierung zu vermeiden. Aber wenn es keine Abkürzungen gibt, werde ich das versuchen. – Truls

0

Eine schmutzige Option, nützlich für kleine Aufzählungen:

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

2007 in Delphi schön Arbeiten Sie wissen nicht, über ältere Versionen. Beachten Sie, dass for Suit in [Hearts..Diamonds] do das gleiche Problem wie Ihre Schleife hat.
BTW, ich benutze WriteLn(), weil ich dies in einer Konsolenanwendung getestet habe. :-)

+0

Danke für den Tipp, ich behalte das im Hinterkopf. Da dieser Fall jedoch ungefähr 30 Elemente enthält, werde ich den const-Ansatz verwenden, der in der akzeptierten Antwort vorgeschlagen wird. – Truls

+0

Nun, selbst mit 30 Elementen sollten Sie immer noch den Bereich aus der ursprünglichen Deklaration kopieren/einfügen können und den Satz einer Konstante zuweisen, die Sie für alle Ihre Loops wiederverwenden. Es hat einen zusätzlichen Bonus: Sie können Elemente zwischen dem Start- und Ende-Element überspringen. –

2

immer

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

Das funktioniert gut, wenn die Enumeration regulär ist, d. H. Fortlaufende Nummern, der Schlüssel hier war jedoch ** nicht aufeinanderfolgende ** Enumeration. – Truls

0

Ich benutze Es sollte verstanden werden (und oft auch nicht), dass der Moment hart Ordnungs Zuweisungen in einer Aufzählung setzen, hört es für alle Absichten ein pascalsche sein aufgezählt Typ - es wird einfach zu einem "Beutel mit Konstanten", was nicht das Gleiche ist. Dies nennen C-Programmierer Aufzählungen. Ein Pascalian-Aufzählungstyp ist jedoch ORDINAL in allen Kriterien: Er hat diskrete aufeinanderfolgende Werte, die sinnvoll auf die Basisoperationen ORD, PRED, SUCC reagieren. Aufzählungen in C tun das nicht, und Enums in Pascal auch nicht, sobald Sie die Ordinalzahlen auseinander drücken.

Dies ist der Grund, warum Delphi's RTTI es grundsätzlich ablehnt, die Typinformationen zurückzugeben, sobald dies erledigt ist. In allen Fällen ist der Typ im Wesentlichen ein tkUnknown und muss als ein "Beutel" von Kompilierzeitkonstanten behandelt werden. Nur weil es Lippenbekenntnisse als Ordinalist hält und (manchmal wackelige) Unterstützung für die Verwendung in Sätzen hat, werden die Leute dazu gebracht zu glauben, dass es sich immer noch wie ein richtig aufgezählten Typ verhalten sollte. Es ist besser, es nur für das zu verstehen, was es wirklich ist: ein Nicken auf aufgezählte Werte in C. Vermeide es, die Codierungsmetapher zu mischen!

Wenn Sie dies tun, wird Ihre Lösung offensichtlich: Sie verwenden einen Aufzählungstyp (einen richtigen), um ein entsprechendes Array von CONSTANTS zu indizieren. Dann können Sie die Ordinalzahlen nach Belieben erstellen, und die Enums behalten ihre vollständigen RTTI-Definitionen als richtige Aufzählung bei. Also: Ihr ENUMERATED TYPE enthält korrekte unveränderte Ordinalwerte. Sie erhalten Ihre lustigen Zahlen durch Indexieren der Konstanten-Array mit der Aufzählung -ergo-Array [MyEnums] von Byte = (1,3,8,22,99, was auch immer)