5

我需要编写一个可以传递不同枚举选择的过程。

type
  TEnumOne = (eOneFlagOne, eOneFlagTwo);
  TEnumTwo = (eTwoFlagOne, eTwoFlagTwo);

该方法应采用不同的枚举:

Process([eOneFlagOne, eTwoFlagTwo]);

我正在尝试像这样实现它:

// does not work!
procedure Process(const Enums: array of Variant);
var aValue; Variant
begin
  for aValue in Enums do
  begin
    // of course, can't work...
    if aValue is TEnumOne then
  end; 
end;

那么,我可以选择一种类型而不是 Variant 吗?或者是一种不同的方法,我不明白?

4

4 回答 4

10

遇见帕斯卡之美。

这是您可能正在尝试做的工作示例:

program Project34; {$APPTYPE CONSOLE}

type
  TEnum=(eOneFlagOne,eOneFlagTwo,eTwoFlagOne,eTwoFlagTwo);
  TEnumSet=set of TEnum;

const
  cEnumOne=[eOneFlagOne,eOneFlagTwo];
  cEnumTwo=[eTwoFlagOne,eTwoFlagTwo];

procedure Process(const Enums: TEnumSEt);
var e:TEnum;
begin
  for e in Enums do
    WriteLn(ord(e));
end;

begin
  Process([eOneFlagOne, eTwoFlagTwo]);
  Process(cEnumOne);
  Process(cEnumTwo);
end.

请注意,您也可以像这样声明常量。也许这更清楚:

const
  cEnumOne:TEnumSet=[eOneFlagOne,eOneFlagTwo];
  cEnumTwo:TEnumSet=[eTwoFlagOne,eTwoFlagTwo];
于 2012-06-19T23:58:04.147 回答
4

坦率地说,当您开始尝试像这样弯曲您的语言时,通常意味着您的方法可能是错误的。(并非总是如此,但通常)我很想听听您要解决什么问题,因为也许有更好的设计选择。

由于我们对您的问题知之甚少,我建议您创建两个具有不同签名的函数。
或者
,如果所需的逻辑分支彼此足够相似,那么您可以使用枚举类型作为通用参数创建一个通用方法(假设 Delphi 2009 或更高版本)。

...
procedure Process<T>(const enumParam : T) // Add a generic constraint here as well
begin
...
end;

然而,在我看来,这两种不同的方法可能是最好的选择(或者完全是别的)

于 2012-06-19T23:56:13.300 回答
1

RRUZ 删除了他的答案,这是一个具有类型安全性的重做版本。RTTI 用于识别不同的枚举常量。

function EnumToString(const TypeInfo : pTypeInfo; Ix : Integer) : string;
begin
  Result := GetEnumName(TypeInfo, ix); 
end;

procedure Process( const Args : array of string);
var
  LIndex,ix : integer;
  EnumOne : TEnumOne;
  EnumTwo : TEnumTwo;
begin
  for LIndex := 0 to High(Args) do begin
    ix := GetEnumValue( TypeInfo(TEnumOne), Args[LIndex]);
    if (ix <> -1) then
    begin
      EnumOne := TEnumOne( ix); 
      // do something with EnumOne
      ...
      continue;
    end;

    ix := GetEnumValue( TypeInfo(TEnumTwo), Args[LIndex]);
    if (ix <> -1) then
    begin
      EnumTwo := TEnumTwo( ix); 
      // do something with EnumTwo
      ...
      continue;
    end; 
    ... 
    etc

  end;        
end;

Process( [EnumToString(TypeInfo(TEnumOne),Ord(TEnumOne.eOneFlagOne)),
          EnumToString(TypeInfo(TEnumTwo),Ord(TEnumTwo.eTwoFlagTwo))]);
于 2012-06-20T14:22:19.223 回答
0

另一种方法是将其保留为一个枚举:

TEnum = (eOneFlagOne, eOneFlagTwo, eTwoFlagOne, eTwoFlagTwo);

Process 函数将如下所示:

procedure Process(Enums: Array of TEnum);
var 
  aValue: TEnum;
begin
  for aValue in Enums do
  begin
    if aValue in [eOneFlagOne, eOneFlagTwo] then
      // Handle the eOne enums
    else if aValue in [eTwoFlagOne, eTwoFlagTwo] then
      // Handle the eTwo enums
  end; 
end;
于 2012-06-20T06:31:09.627 回答