I'm trying to write functions that will convert an enumeration to string and back again.
ie:
TConversions = class
strict private
public
class function StringToEnumeration<T:class>(x:String):T;
class function EnumerationToString<T:class>(x:T):String;
end;
in the implementation section I have
uses
System.TypInfo
;
class function TConversions.StringToEnumeration<T>(x:String):T;
begin
Result := T(GetEnumValue(TypeInfo(T), x));
end;
class function TConversions.EnumerationToString<T>(x:T):String;
begin
Result := GetEnumName(TypeInfo(T), integer(x));
end;
The problem is, an enum is not of type T:class
in pascal. I can't use T:record
either.
Is this possible to do in pascal?
The following code loops through enum and adds string values to a DropDownList. This code converts an enum to string: string name= Enum. GetName(typeof(ArrayListBinding.
Use const char* Array to Convert an Enum to a String in C++ enum is a built-in type, which can be used to declare small named integers usually formed as an array. This mechanism provides a less error-prone and more readable way of representing a set of integer values.
The stringify() macro method is used to convert an enum into a string. Variable dereferencing and macro replacements are not necessary with this method. The important thing is that, only the text included in parenthesis may be converted using the stringify() method.
To convert string to enum use static method Enum. Parse. Parameters of this method are enum type, the string value and optionally indicator to ignore case.
You need to fiddle with things a bit. There is no generic for enums so we get around it by casting to and from the enum using Byte, Word and Cardinal.
program Project6;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils, System.TypInfo;
type
TConversions<T> = record
class function StringToEnumeration(x: String): T; static;
class function EnumerationToString(x: T): String; static;
end;
class function TConversions<T>.StringToEnumeration(x: String): T;
begin
case Sizeof(T) of
1: PByte(@Result)^ := GetEnumValue(TypeInfo(T), x);
2: PWord(@Result)^ := GetEnumValue(TypeInfo(T), x);
4: PCardinal(@Result)^ := GetEnumValue(TypeInfo(T), x);
end;
end;
class function TConversions<T>.EnumerationToString(x: T): String;
begin
case Sizeof(T) of
1: Result := GetEnumName(TypeInfo(T), PByte(@x)^);
2: Result := GetEnumName(TypeInfo(T), PWord(@x)^);
4: Result := GetEnumName(TypeInfo(T), PCardinal(@x)^);
end;
end;
type
TMyEnum = (me_One, me_Two, me_Three);
TMyEnum2 = (m1,m2,m3,m4,m5,m6,m7,m8,m9,m10,m11,m12,m13,m14,m15,m16,m17,m18,m19,m20,
m21,m22,m23,m24,m25,m26,m27,m28,m29,m30,m31,m32,m33,m34,m35,m36,m37,m38,m39,m40,
m41,m42,m43,m44,m45,m46,m47,m48,m49,m50,m51,m52,m53,m54,m55,m56,m57,m58,m59,m60,
ma1,ma2,ma3,ma4,ma5,ma6,ma7,ma8,ma9,ma10,ma11,ma12,ma13,ma14,ma15,ma16,ma17,ma18,ma19,ma20,
ma21,ma22,ma23,ma24,ma25,ma26,ma27,ma28,ma29,ma30,ma31,ma32,ma33,ma34,ma35,ma36,ma37,ma38,ma39,
ma40,ma41,ma42,ma43,ma44,ma45,ma46,ma47,ma48,ma49,ma50,ma51,ma52,ma53,ma54,ma55,ma56,ma57,ma58,ma59,ma60,
mb1,mb2,mb3,mb4,mb5,mb6,mb7,mb8,mb9,mb10,mb11,mb12,mb13,mb14,mb15,mb16,mb17,mb18,mb19,
mb20,mb21,mb22,mb23,mb24,mb25,mb26,mb27,mb28,mb29,mb30,mb31,mb32,mb33,mb34,mb35,mb36,mb37,mb38,mb39,
mb40,mb41,mb42,mb43,mb44,mb45,mb46,mb47,mb48,mb49,mb50,mb51,mb52,mb53,mb54,mb55,mb56,mb57,mb58,mb59,mb60,
mc1,mc2,mc3,mc4,mc5,mc6,mc7,mc8,mc9,mc10,mc11,mc12,mc13,mc14,mc15,mc16,mc17,mc18,mc19,
mc20,mc21,mc22,mc23,mc24,mc25,mc26,mc27,mc28,mc29,mc30,mc31,mc32,mc33,mc34,mc35,mc36,mc37,mc38,mc39,
mc40,mc41,mc42,mc43,mc44,mc45,mc46,mc47,mc48,mc49,mc50,mc51,mc52,mc53,mc54,mc55,mc56,mc57,mc58,mc59,mc60,
md1,md2,md3,md4,md5,md6,md7,md8,md9,md10,md11,md12,md13,md14,md15,md16,md17,md18,md19,
md20,md21,md22,md23,md24,md25,md26,md27,md28,md29,md30,md31,md32,md33,md34,md35,md36,md37,md38,md39,
md40,md41,md42,md43,md44,md45,md46,md47,md48,md49,md50,md51,md52,md53,md54,md55,md56,md57,md58,md59,md60,
me1,me2,me3,me4,me5,me6,me7,me8,me9,me10,me11,me12,me13,me14,me15,me16,me17,me18,me19,
me20,me21,me22,me23,me24,me25,me26,me27,me28,me29,me30,me31,me32,me33,me34,me35,me36,me37,me38,me39,
me40,me41,me42,me43,me44,me45,me46,me47,me48,me49,me50,me51,me52,me53,me54,me55,me56,me57,me58,me59,me60,
mf1,mf2,mf3,mf4,mf5,mf6,mf7,mf8,mf9,mf10,mf11,mf12,mf13,mf14,mf15,mf16,mf17,mf18,mf19,
mf20,mf21,mf22,mf23,mf24,mf25,mf26,mf27,mf28,mf29,mf30,mf31,mf32,mf33,mf34,mf35,mf36,mf37,mf38,mf39,
mf40,mf41,mf42,mf43,mf44,mf45,mf46,mf47,mf48,mf49,mf50,mf51,mf52,mf53,mf54,mf55,mf56,mf57,mf58,mf59,mf60);
var
enum: TMyEnum;
enum2: TMyEnum2;
begin
enum := me_Two;
WriteLn(TConversions<TMyEnum>.EnumerationToString(enum));
enum := me_One;
WriteLn(TConversions<TMyEnum>.EnumerationToString(enum));
enum := TConversions<TMyEnum>.StringToEnumeration('me_Three');
WriteLn(TConversions<TMyEnum>.EnumerationToString(enum));
enum2 := m17;
WriteLn(TConversions<TMyEnum2>.EnumerationToString(enum2));
ReadLn;
end.
Somehow this crucial information is missing as an answer:
In recent Delphi versions there is no need to write any generic helper to convert enums to string and back, because it is already there in System.Rtti
, and in fact it is implemented very similar to the existing answers here.
class function TRttiEnumerationType.GetName<T{: enum}>(AValue: T): string;
class function TRttiEnumerationType.GetValue<T{: enum}>(const AName: string): T;
Usage is very short and simple:
S:= TRttiEnumerationType.GetName(myEnum);
There seems to be no T:enum
generic type constraint so I think the best you can do is check the type at runtime, something like this:
Edit: Based on David's comment, I've added the T: record
constraint which can be used to constrain to value types (and rule out class types).
type
TConversions = class
public
class function StringToEnumeration<T: record>(const S: string): T;
class function EnumerationToString<T: record>(Value: T): string;
end;
class function TConversions.EnumerationToString<T>(Value: T): string;
var
P: PTypeInfo;
begin
P := PTypeInfo(TypeInfo(T));
case P^.Kind of
tkEnumeration:
case GetTypeData(P)^.OrdType of
otSByte, otUByte:
Result := GetEnumName(P, PByte(@Value)^);
otSWord, otUWord:
Result := GetEnumName(P, PWord(@Value)^);
otSLong, otULong:
Result := GetEnumName(P, PCardinal(@Value)^);
end;
else
raise EArgumentException.CreateFmt('Type %s is not enumeration', [P^.Name]);
end;
end;
class function TConversions.StringToEnumeration<T>(const S: string): T;
var
P: PTypeInfo;
begin
P := PTypeInfo(TypeInfo(T));
case P^.Kind of
tkEnumeration:
case GetTypeData(P)^.OrdType of
otSByte, otUByte:
PByte(@Result)^ := GetEnumValue(P, S);
otSWord, otUWord:
PWord(@Result)^ := GetEnumValue(P, S);
otSLong, otULong:
PCardinal(@Result)^ := GetEnumValue(P, S);
end;
else
raise EArgumentException.CreateFmt('Type %s is not enumeration', [P^.Name]);
end;
end;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With