navirius
navirius

Reputation: 317

delphi - how to get type of enum

I know how to get enum value from integer value, and I have this code

function GetEnumValue(intValue:integer):TMyType
begin
   if(ordValue >= Ord(Low(TMyType)))and(ordValue <= Ord(High(TMyType)))then 
      result :=TMyType(ordValue)
   else 
      raise Exception.Create('ordValue out of TMyType range');
end;

I have similiar code like above in many place for many enum type other than TMyType, I want encapsulate that code to single protected code on base class, so inherited class can use it.

but I dont know how to generalize TMyType, so my code can check if it right enum type or another type object

I cant have a clue what a enum base class (like TObject for all of object type or TControl for all of VCL type), then I can check like that code

Upvotes: 2

Views: 5402

Answers (1)

LU RD
LU RD

Reputation: 34909

There is no such thing as a base type for an enumeration type, like TObject is the base for classes.

If you have a Delphi version that supports generics, you can use following helper to make a generic cast from an ordinal value to an enumeration value.

uses
  System.SysUtils,TypInfo;

Type
  TEnumHelp<TEnum> = record
  type
    ETEnumHelpError = class(Exception);
    class function Cast(const Value: Integer): TEnum; static;
  end;

class function TEnumHelp<TEnum>.Cast(const Value: Integer): TEnum;
var
  typeInf  : PTypeInfo;
  typeData : PTypeData;
begin
  typeInf := PTypeInfo(TypeInfo(TEnum));
  if (typeInf = nil) or (typeInf^.Kind <> tkEnumeration) then
    raise ETEnumHelpError.Create('Not an enumeration type');
  typeData := GetTypeData(typeInf);
  if (Value < typeData^.MinValue) then
    raise ETEnumHelpError.CreateFmt('%d is below min value [%d]',[Value,typeData^.MinValue])
  else
  if (Value > typeData^.MaxValue) then
    raise ETEnumHelpError.CreateFmt('%d is above max value [%d]',[Value,typeData^.MaxValue]);
  case Sizeof(TEnum) of
    1: pByte(@Result)^ := Value;
    2: pWord(@Result)^ := Value;
    4: pCardinal(@Result)^ := Value;
  end;
end;

Example:

Type
  TestEnum = (aA,bB,cC);

var
  e : TestEnum;
...
e := TEnumHelp<TestEnum>.Cast(2);  // e = cC

There is one limitation:

Enumerations that are discontiguous or does not start with zero, have no RTTI TypeInfo information. See RTTI properties not returned for fixed enumerations: is it a bug?.

Upvotes: 4

Related Questions