7

我正在使用 Delphi 6 Professional。我正在与一个声明数字类型的 DLL 库接口,如下所示:

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

如您所见,初始化值不连续。如果我尝试使用 for 循环迭代类型,如下所示:

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

Delphi 仍然在每次循环调用时将 e 递增 1,从而为 e 创建不是枚举类型成员的数值(例如,'3'),并导致“超出范围”错误。如何在只为枚举类型生成有效值的 for 循环中迭代枚举类型?

谢谢。

4

4 回答 4

13

通过定义一组常量...

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.

并作为迭代器实现 - 只是为了好玩......

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.
于 2010-09-28T23:18:11.897 回答
7

据我所知,没有办法以你想要的方式迭代。如果枚举不经常更改,解决方法可能是声明一个“索引数组”,它可以让您以您想要的方式进行迭代。诀窍是您不要遍历枚举,而是遍历一个索引,然后您可以将其“转换”为枚举中的有效元素:

我想我可以用代码更好地解释这个想法:

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;
于 2010-09-28T22:55:55.410 回答
4

定义枚举时

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

您实际上定义了由 17 ($10 + 1) 个可能值组成的枚举类型。这是有据可查的。

有很多方法可以仅在分配的枚举常量上实现迭代(请参阅其他答案),但是您这样做的方式是迭代 17 个值,并且无法更改。

这是另一个迭代示例,它使用了除 ENUM1 之外的所有 ENUMx 值都是 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;
于 2010-09-28T23:13:07.880 回答
3

你不能

如果值是二进制加权的,请尝试使用这样的 while 循环

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

end;
于 2010-09-28T23:04:46.670 回答