Generics, Enumerated types and ordinal values

I wish this was a solution post, but it is a frustration post. I trying to figure out how I can use Ord() to convert an enumerated type to integer or cast an integer to an enumerated type using generics type arguments?

uses
SysUtils,
TypInfo;

type
TSomeEnumType = (TheFirst, TheSecond, TheThird, TheFourth);

type
TEnumGen = class
class function Name(const Enum:TEnumType):String;
class function Value(const Ordinal:Integer):TEnumType;
end;

class function TEnumGen.Name(const Enum: TEnumType): String;
begin
Result := Format('%s.%s',
[GetTypeName(TypeInfo(TEnumType)),
GetEnumName(TypeInfo(TEnumType), Ord(Enum)) // <-- Bombs
]);
end;

class function TEnumGen.Value(const Ordinal:Integer):TEnumType;
begin
Result := TEnumType(Ordinal); // <- Bombs
end;

Unfortunately there is no “enum” delimiter that can be used to tell the compiler that Ord() and casting of integers should be allowed for generic enumerated type arguments.

10 thoughts on “Generics, Enumerated types and ordinal values

  1. This should work (assuming Blogger doesn't eat it for dinner):class function TEnumGen.Name(const Enum: TEnumType): String;var Info: PTypeInfo; OrdValue: Integer;begin Info := TypeInfo(TEnumType); case GetTypeData(Info).OrdType of otSByte: OrdValue := PShortInt(@Enum)^; otUByte: OrdValue := PByte(@Enum)^; otSWord: OrdValue := PWord(@Enum)^; otUWord: OrdValue := PSmallInt(@Enum)^; otSLong: OrdValue := PLongWord(@Enum)^; otULong: OrdValue := PLongInt(@Enum)^; else raise EProgrammerNotFound.Create('New TOrdType element!'); end; Result := Format('%s.%s', [GetTypeName(Info), GetEnumName(Info, OrdValue)]);end;class function TEnumGen.Value(const Ordinal:Integer):TEnumType;begin Move(Ordinal, Result, SizeOf(TEnumType));end;

    Like

  2. Blogger was indeed hungry I see, if hardly famished… Obviously, it would be better if there were an ordinal type constraint (along with operator constraints and so on), but my suggested solution is quite general.

    Like

  3. TValue is your friend! :)class function TEnumGen.Name(const Enum: TEnumType): String;var  i: Int64;begin  TValue.From(Enum).TryAsOrdinal(i);  Result := Format('%s.%s', [GetTypeName(TypeInfo(TEnumType)), GetEnumName(TypeInfo(TEnumType), i)]);end;class function TEnumGen.Value(const Ordinal:Integer): TEnumType;var  v: TValue;begin  TValue.Make(Ordinal, TypeInfo(TEnumType), v);  Result := v.AsType;end;

    Like

  4. Stefan – nice! In fact, that allows doing away with an explicit call to GetEnumName entirely -class function TEnumGen.Name(const Enum: TEnumType): String;var  Value: TValue;begin  TValue.From(Enum);  Result := Format('%s.%s', [GetTypeName(Value.TypeInfo), Value.ToString]);end;

    Like

  5. Oh yes, even better that way, Chris.And you can also do it like this: Format('%s.%s', [v.TypeInfo.Name, v.ToString]);I really like TValue 🙂

    Like

  6. Hi,Had a similar need when started with generics back with RAD 2009 and solved the cast this way:class function Generic.EnumToInt(const EnumValue: T): Integer;begin Result := 0; Move( EnumValue, Result, sizeOf(EnumValue) );end;class function Generic.IntToEnum(const IntValue: Integer): T;begin Move( IntValue, Result, SizeOf(Result) );end;which can be used as follows:class function Generic.StringToEnum(StringValue: string): T;begin Result := Generic.IntToEnum(getEnumValue( TypeInfo(T), StringValue ));end;class function Generic.EnumToString(EnumValue: T): string;begin Result := getEnumName( TypeInfo(T), Generic.EnumToInt(EnumValue) );end;but I agree TValue seems a more clean solution.

    Like

  7. Take a look at http://cc.embarcadero.com/item/27397TEnumtypeTJim = (jjHigh,jjLow,jjHello_There);varJ: TEnum;S: String;Strs: TStrings;I: Integer;begin// Implicit assign of the friendly stringJ := 'Hello There';// implicit assign of enumorated name asJ := 'jjHello_There'; string// implicit ordinal assignJ := 2;// implicit assign of enumoratedtypeJ := jjHello_There;// This uses casting to select the proper implicit conversionWriteLn(String(J),'(',Integer(I),')');// Output should be 'Hello There(2)'// Add the enumorated type value to TStringsStrs.Add(J);end.

    Like

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.