2010-11-09 21 views
6

1) ¿Alguien sabe si es posible colocar a través de una enumeración irregular en Delphi (XE)?Bucle a través de la enumeración irregular en Delphi

Looping sobre una enumeración normal está bien. De Delphi Basics:

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

Pero, si 'traje' en su lugar se declara como

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

se realiza un bucle 10 veces. No es sorprendente, pero me gustaría hacer un bucle 3. La única solución que he encontrado hasta ahora es convertir una enumeración en un conjunto y usar el bucle 'for ... in' como en delphi.about.com.

Entonces, si la respuesta a la pregunta 1) es no, entonces:
2) ¿Cómo convertir de enumeración a establecer en Delphi?

El contexto en el que lo estoy usando es una matriz de componentes de cuadros de edición (TEdit) que tiene una numeración irregular (edición1, edición5, edición7, edición3, ...). Si bien es posible reordenar todas las cajas de edición, se elimina la razón de usar la enumeración como una forma flexible de permitir la adición de una caja de edición en el medio de la enumeración.

+0

¿Por qué no puede usar algún descendiente 'TList' y iterar sobre eso? –

+0

La enumeración se usará como índice en matrices de TLabels, TEdits y Strings para que pueda usar StringArray [Job]: = Editbox [Job]. TList podría funcionar, pero el objetivo era facilitar la lectura del código fuente mediante el uso de enumeraciones (irregulares) como índices, como HashMap en Java. Lo que veo ahora probablemente no funcione ... – Truls

+0

¿Has intentado utilizar XEs RTTI? El RTTI ordinario de la unidad 'TypInfo' falla miserablemente. Aparentemente no se puede obtener 'TypeInfo()' en una enumeración irregular, también probé con un conjunto y las violaciones de acceso me dieron acceso. –

Respuesta

7

que no tienen un compilador de Delphi que nos ocupa en este momento, pero yo Tink que el enfoque de gabr puede ser más bien mejoró significativamente haciendo

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

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

Quién sabe, a lo mejor ni siquiera compilar.

+0

Definitivamente debería funcionar. – gabr

+0

¡Ha probado esto y funciona! Gracias. Si alguien sabe si es posible evitar repetir la lista de enumeraciones, me gustaría saberlo. – Truls

0

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

+2

Creo que Ord (Corazones) a Ord (Picas) repetirá 11 veces, y no 3 como quiero. – 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

Gracias por la sugerencia. Como tengo alrededor de 30 elementos en mi enumeración, esperaba evitar la inicialización manual. Pero si no hay atajos, intentaré eso. – Truls

0

Una opción sucio, útil para las pequeñas enumeraciones:

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

funciona agradable en Delphi 2007. No sé acerca de las versiones más antiguas. Tenga en cuenta que usar for Suit in [Hearts..Diamonds] do tiene el mismo problema que su ciclo.
Por cierto, yo uso WriteLn() porque probé esto en una aplicación de consola. :-)

+0

Gracias por el consejo, lo tendré en cuenta. Sin embargo, dado que este caso tiene alrededor de 30 elementos, usaré el enfoque const sugerido en la respuesta aceptada. – Truls

+0

Bueno, incluso con 30 elementos, aún debería poder copiar/pegar el rango de su declaración original y asignar el conjunto a alguna constante que reutilice para todos sus bucles. Tiene una ventaja adicional: puede omitir elementos entre el elemento inicial y final. –

2

siempre uso

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

Eso funciona bien si la enumeración es regular, es decir, números consecutivos, pero la clave aquí fue ** enumeración no consecutiva **. – Truls

0

Debe entenderse (y, a menudo no lo es) que el momento de poner las asignaciones ordinales duros en una enumeración, deja para todos los intentos para ser un pascaliano enumerado tipo - simplemente se convierte en una "bolsa de constantes", que no es lo mismo. Esto es lo que los programadores en C llaman enumeraciones. Sin embargo, un tipo enumerado de Pascal es ORDINAL en todos los criterios: Tiene valores discretos consecutivos que responden de manera significativa a las operaciones base ORD, PRED, SUCC. Las enumeraciones en C no hacen esto, y tampoco las enumeraciones en Pascal una vez que se separan los ordinales.

Ésta es la razón de que RTTI de Delphi, básicamente, se niega a devolver información de tipo una vez que esto se ha hecho. A todos los efectos, el tipo es esencialmente un tkUnknown, y debe tratarse como una "bolsa" de constantes en tiempo de compilación. Es solo porque todavía se comporta como un ordinal y tiene (a veces inestable) soporte para el uso en conjuntos que las personas son inducidas a creer que todavía debería comportarse como un tipo enumerado apropiado. Es mejor simplemente entenderlo por lo que realmente es: un guiño a los valores enumerados en C. ¡Evite mezclar la metáfora de codificación!

Si hace esto, su solución se vuelve obvia: utiliza un tipo enumerado (uno adecuado) para indexar una matriz correspondiente de CONSTANTS. Luego puedes hacer los ordinales como quieras, y las enumeraciones retienen sus definiciones completas de RTTI como una enumeración correcta. Entonces: su TIPO ENUMERADO contiene los valores ordinales correctos sin modificar. Obtiene sus números divertidos indexando la matriz de constantes usando la enumeración -ergo array [MyEnums] of byte = (1,3,8,22,99, cualquiera)

Cuestiones relacionadas