【问题标题】:How to check if an integer can be converted to an enumeration type value?如何检查整数是否可以转换为枚举类型值?
【发布时间】:2019-12-13 12:01:23
【问题描述】:

我在我的枚举器类型上定义了一个InRange 函数。如果传递的整数参数可以转换为枚举类型,函数应该返回True

  TMyEnum = (eA, eB);
  TMyEnumHelper = record helper for TMyEnum
    class function InRange(AValue : integer) : Boolean; static;
  end;

...

class function TMyEnumHelper.InRange(AValue : integer) : Boolean;
begin
  Result :=
    (AValue >= Low(TMyEnum)) and
    (AValue <= High(TMyEnum));
end;

在编译时,在(AValue &gt;= Low(TMyEnum)) 行,我收到以下错误:

[dcc32 错误] Unit1.pas(34): E2008 不兼容类型

我做了一些测试,但我真的不明白出了什么问题...... 即:

  1. 我尝试将InRange函数的AValue参数类型切换为ByteShortIntWordSmallIntLongWordCardinal、@9876543333@、 @ 和 Int64,但在编译时会引发同样的错误。
  2. 如果我将枚举数定义为TMyEnum = 0..1;,则编译不会出错。

【问题讨论】:

    标签: delphi enums delphi-xe7


    【解决方案1】:

    您不能直接将枚举值与整数进行比较。您必须将枚举值转换为整数值才能进行比较:

    class function TMyEnumHelper.InRange(AValue : integer) : Boolean;
    begin
      Result :=
        (AValue >= Ord(Low(TMyEnum))) and
        (AValue <= Ord(High(TMyEnum)));
    end;
    

    注意添加的“ord”转换,它将其“参数”(括号内的表达式)转换为整数值。

    你的原因

    TMyEnum = 0..1;
    

    有效的是这不是枚举,而是整数子范围,因此 TMyEnum 的基本类型是整数而不是枚举。

    【讨论】:

    • 感谢您的解释。我没有考虑 Low(TMyEnum)High(TMyEnum) 正在返回 TMyEnum
    • @Fabrizio 这样你就可以写 FOR EnumVar:=LOW(TMyEnum) TO HIGH(TMyEnum)
    【解决方案2】:

    您还可以使用泛型而不是助手来使InRange 支持所有枚举类型:

    uses
      SysUtils, TypInfo;
    
    type
      TMyEnum1 = (me1A, me1B);
      TMyEnum2 = (me2A, me2B, me2C);
      TMyEnum3 = (me3A = 1, me3B = 3);
    
      TEnum = class
        class function InRange<T>(const AValue: Integer): Boolean; static;
      end;
    
    { TEnum }
    
    class function TEnum.InRange<T>(const AValue: Integer): Boolean;
    var
      TI: PTypeInfo;
      TD: PTypeData;
    begin
      TI := TypeInfo(T);
    
      if not Assigned(TI) then
        raise Exception.Create('InRange does not support discontinuous enumerations.');
    
      if TI^.Kind <> tkEnumeration then
        raise Exception.Create('InRange only supports enumeration types.');
    
      TD := GetTypeData(TI);
      Result :=
        (AValue >= TD^.MinValue) and
        (AValue<=TD^.MaxValue);
    end;
    
    begin
      try
        Writeln(BoolToStr(TEnum.InRange<TMyEnum1>(2), true));
        Writeln(BoolToStr(TEnum.InRange<TMyEnum2>(2), true));
        Writeln(BoolToStr(TEnum.InRange<TMyEnum3>(2), true));
      except
        on E: Exception do
          Writeln(E.ClassName, ': ', E.Message);
      end;
        Readln;
    end.
    

    产生:

    错误
    真的
    例外:InRange 不支持不连续的枚举。

    请注意,如果为TMyEnum3 实施,您当前的方法将为AValue=2 返回True

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-02-12
      • 2015-01-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-24
      • 1970-01-01
      相关资源
      最近更新 更多