2010-09-28 7 views
7

Ich benutze Delphi 6 Professional. Ich bin einer Schnittstelle mit einer DLL libraty, die eine enumberated Art erklärt sich wie folgt:Wie man initialisierte Aufzählungstypen mit Delphi 6 iteriert und den "out of bounds" -Fehler vermeidet?

TExtDllEnum = (ENUM1 = $0, ENUM2 = $1, ENUM3 = $2, ENUM4 = $4, ENUM5 = $8, ENUM6 = $10); 

Wie Sie die initialisierten Werte sehen können, sind nicht zusammenhängend. Wenn ich versuche, die Art mit einer for-Schleife zu durchlaufen, wie folgt:

var 
    e: TExtDllEnum; 
begin 
    for e := Low(TExtToDllEnum) to High(TExtToDllEnum) do 
    ... // More code 
end; 

Delphi noch e um 1 jede Schleife Aufruf inkrementiert und schafft damit numerische Werte für E, die keine Mitglieder des aufgezählten Typs sind (beispielsweise ' 3 ') und zu einem' Out-of-bounds'-Fehler führen. Wie kann ich den Aufzählungstyp in einer for-Schleife wiederholen, die nur gültige Werte für den Aufzählungstyp generiert?

Danke.

Antwort

13

Durch eine Reihe von Konstanten definieren ...

type 
    TExtDllEnum = (ENUM1 = $0, ENUM2 = $1, ENUM3 = $2, ENUM4 = $4, ENUM5 = $8, ENUM6 = $10); 

const 
    CExtDllEnumSet = [ENUM1, ENUM2, ENUM3, ENUM4, ENUM5, ENUM6]; 


var 
    e: TExtDllEnum; 
begin 
    e := Low(TExtDllEnum); 
    while e <= High(TExtDllEnum) do 
    begin 
    if e in CExtDllEnumSet then 
     WriteLn(Ord(e)); 

    Inc(e); 
    end; 

    ReadLn; 
end. 

und als Iterator implementiert - nur zum Spaß ...

type 
    TExtDllEnum = (ENUM1 = $0, ENUM2 = $1, ENUM3 = $2, ENUM4 = $4, ENUM5 = $8, ENUM6 = $10); 
const 
    CExtDllEnumSet = [ENUM1, ENUM2, ENUM3, ENUM4, ENUM5, ENUM6]; 

type 
    TMyIterator = class 
    private 
    FValue: TExtDllEnum; 
    public 
    constructor Create; 
    function Next: TExtDllEnum; 
    function HasNext: Boolean; 
    end; 

    constructor TMyIterator.Create; 
    begin 
    FValue := Low(TExtDllEnum); 
    end; 

    function TMyIterator.HasNext: Boolean; 
    begin 
    Result := FValue <= High(TExtDllEnum); 
    end; 

    function TMyIterator.Next: TExtDllEnum; 
    begin 
    Result := FValue; 

    repeat 
     Inc(FValue); 
    until (FValue in CExtDllEnumSet) or (FValue > High(TExtDllEnum)) 
    end; 

var 
    MyIterator: TMyIterator; 
begin 
    MyIterator := TMyIterator.Create; 

    while MyIterator.HasNext do 
    WriteLn(Ord(MyIterator.Next)); 

    MyIterator.Free; 

    ReadLn; 
end. 
7

Soweit ich mich erinnern kann, gibt es keine Möglichkeit zu iterieren, wie Sie wollen. Wenn die Enumeration nicht häufig geändert wird, besteht die Problemumgehung möglicherweise darin, ein "Indexarray" zu deklarieren, mit dem Sie die gewünschten Schritte ausführen können. Der Trick ist, dass Sie nicht über die Aufzählung laufen, sondern über einen Index, die Sie wiederum „convert“ auf ein gültiges Element in der ENUM können:

Ich denke, dass ich die Idee besser im Code erklären kann:

const 
    ExtDllEnumElements = 6; 
    EnumIndexArray: array[0..ExtDllEnumElements - 1] of TExtDllEnum = (ENUM1, ENUM2, ENUM3, ENUM4, ENUM5, ENUM6); 
var 
    I: Integer; 
begin 
    for I := Low(EnumIndexArray) to High(EnumIndexArray) do 
    WhateverYouWantWith(EnumIndexArray[I]); 
end; 
3

Sie können nicht

, wenn die Werte binär gewichtet versuchen, eine while-Schleife wie diese

var 
    e: TExtDllEnum; 
begin 
    e := 0; 
    While e <= High(TExtToDllEnum) do 
    begin 
     ... // More code 
     e := Power(2, e); 
    end; 

end; 
4

Verwendung wenn Sie die Aufzählung definieren

TExtDllEnum = (ENUM1 = $0, ENUM2 = $1, ENUM3 = $2, ENUM4 = $4, ENUM5 = $8, ENUM6 = $10); 

Sie definieren tatsächlich den Aufzählungstyp bestehend aus 17 ($ 10 + 1) möglichen Werten. Das ist documented.

Es gibt viele Möglichkeiten, die Iteration nur über zugewiesenen Enumerationskonstanten zu implementieren (siehe die anderen Antworten), aber die Art und Weise, wie Sie es tun, iteriert über 17 Werte, die nicht geändert werden können.

Hier ist eine weitere Iteration Beispiel, das die Tatsache nutzt, dass alle ENUMx Werte außer ENUM1 Potenzen von 2:

type 
    TExtDllEnum = (ENUM1 = $0, ENUM2 = $1, ENUM3 = $2, 
       ENUM4 = $4, ENUM5 = $8, ENUM6 = $10); 
var 
    e: TExtDllEnum; 

begin 
    e:= Low(TExtDllEnum); 
    repeat 
    [..] 
    if e = ENUM1 then e:= ENUM2 
    else if e = High(TExtDllEnum) then Break 
    else e:= e shl 1; 
    until False; 
end;