【问题标题】:Pass a mixture of differend enums types in delphi在 delphi 中传递不同枚举类型的混合
【发布时间】:2012-06-22 01:36:38
【问题描述】:

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

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 吗?或者是另一种方法,我不明白?

【问题讨论】:

  • 内存不足,如果我没记错的话,您可以将枚举转换为整数,例如I:= Integer(eOneFlagOne);F:= TEnumOne(I);,在这种情况下,如果eOneFlagOne = 0然后eTwoFlagOne = 0 也是。除非您想要更多的唯一 ID,例如 0,1/2,3 而不是 0,1/0,1,在这种情况下,我不知道。
  • 或者,作为替代方案,使用常量代替,例如,const E_ONE_FLAG_ONE = 0; E_ONE_FLAG_TWO = 1; E_TWO_FLAG_ONE = 2; E_TWO_FLAG_TWO = 3; 等,并使用这些代替枚举。
  • 顺便说一句,我确定 RRUZ 要求该版本可能是因为 XE2 等较新版本可能会提供更简单的方法...
  • 你的设计听起来有缺陷。我不会与语言抗争,而是重新考虑设计。对于它的价值,为了编写类似 if aValue is TEnumOne 的东西,您显然需要使用类而不是枚举。这些类可以保存枚举。
  • 我正在使用 Delphi XE。问题是,枚举是由 remobjects 作为接口自动生成的。所以我不能改变枚举的定义。

标签: arrays delphi enums


【解决方案1】:

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

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

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

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

【讨论】:

    【解决方案2】:

    遇见帕斯卡之美。

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

    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];
    

    【讨论】:

    • 要完成此操作,您需要 TEnumOne = eOneFlagOne..eOneFlagTwo 等
    • 遗憾的是,我无法更改或扩展 enmus 的类型定义。我也无法建立一套。
    • @FrancoisZbinden 如果无法更改枚举的类型定义,并且无法构建集合,则应更改 Process-function,使其接受两个参数,Process(EnumOneArray: Array of TEnumOne; EnumTwoArray: TEnumTwo 的数组),然后检查两个数组中的条件。
    【解决方案3】:

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

    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;
    

    【讨论】:

    • 这只是重复 Wouter 的回答。除非你添加一些新奇的东西,否则它只是混乱
    • 与这样的开放参数数组相比,使用集合(如 Wouter 提议)对于 pascal 语言来说更加原生和高效。
    • @ArnaudBouchez 我同意。但是,实际上这并不重要。只有函数是需要高度优化的核心循环的一部分才有意义。
    【解决方案4】:

    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))]);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-12-15
      • 1970-01-01
      • 2019-05-26
      • 1970-01-01
      • 2021-12-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多