La forma de repetición inicializado tipos enumerados con Delphi 6 y evitar el error “fuera de límites”?

StackOverflow https://stackoverflow.com/questions/3817565

Pregunta

Estoy utilizando Delphi 6 Professional. Estoy de interfaz con un Libraty DLL que declara un tipo enumberated de la siguiente manera:

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

Como se puede ver los valores inicializados no son contiguas. Si intento para iterar el tipo utilizando un bucle como sigue:

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

Delphi todavía incrementa e por 1 cada invocación de bucle y de este modo crea valores numéricos para e que no son miembros del tipo enumerado (por ejemplo, '3'), y que resulta en un 'fuera de límites' error. ¿Cómo puedo iterar el tipo enumerado en un bucle for que genera solamente valores válidos para el tipo enumerado?

Gracias.

¿Fue útil?

Solución

Al definir un conjunto de constantes ...

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 implementado como un iterador - sólo por diversión ...

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.

Otros consejos

Por lo que yo puedo recordar, no hay manera de iterar la manera deseada. Si la enumeración no se cambia con frecuencia, una solución puede ser la de declarar una "matriz de índice", que le permiten iterar la manera deseada. El truco es no lo hace iterar sobre la enumeración, pero en un índice que se puede convertir en "convertir" a un elemento válido en la enumeración:

Creo que puedo explicar mejor la idea de código:

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;

Cuando se define la enumeración

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

que realmente definen el tipo de enumeración que consiste en 17 ($ 10 + 1) valores posibles. Es decir documentados .

Hay muchas formas de implementar la iteración más constantes de enumeración asignado solamente (ver las otras respuestas), pero la forma en que lo están haciendo iterar más de 17 valores, y que no se puede cambiar.

Aquí está una más iteración ejemplo que utiliza el hecho de que todos los valores excepto ENUMx Enum1 son potencias de 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;

No se puede

si los valores son try ponderado binario utilizando un tiempo de bucle como este

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

end;
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top