2010-09-28 13 views
7

Sto usando Delphi 6 Professional. Sto interfacciamento con un Libraty DLL che dichiara un tipo enumberated come segue:Come ripetere i tipi enumerati inizializzati con Delphi 6 ed evitare l'errore "fuori dai limiti"?

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

Come potete vedere i valori inizializzati non sono contigue. Se provo a iterare il tipo utilizzando un ciclo come segue:

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

Delphi incrementa ancora e di 1 ogni invocazione ciclo e quindi crea valori numerici e che non sono membri del tipo enumerato (per esempio, ' 3 ') e risultante in un errore' fuori limite '. Come posso iterare il tipo enumerato in un ciclo for che genera solo valori validi per il tipo enumerato?

Grazie.

risposta

13

Definendo una serie di costanti ...

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. 

e implementato come iteratore - solo per divertimento ...

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

Per quanto posso ricordare, non è possibile iterare nel modo desiderato. Se l'enumerazione non viene modificata di frequente, una soluzione alternativa potrebbe essere dichiarare una "serie di indici", che consente di eseguire iterazioni nel modo desiderato. Il trucco è che non iterare l'enumerazione, ma nel corso di un indice che si può a sua volta "convertire" ad un elemento valido nel enum:

credo di poter spiegare la migliore idea in codice:

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

non è possibile

se i valori sono binari provare ponderata utilizzando un ciclo while come questo

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

end; 
4

Quando si definisce l'enumerazione

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

in realtà si definisce il tipo di enumerazione costituito da 17 valori ($ 10 + 1) possibili. Questo è documented.

Esistono molti modi per implementare l'iterazione rispetto alle costanti di enumerazione assegnate (vedere le altre risposte), ma nel modo in cui lo stai eseguendo si eseguono iterazioni su 17 valori e questo non può essere modificato.

Ecco un altro esempio iterazione che utilizza il fatto che tutti i valori ENUMx eccetto ENUM1 sono potenze di 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; 
Problemi correlati