本文介绍了如何使用通用枚举类型调用GetEnumName?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述 我有一个泛型类,它使用枚举通用类型。我的问题如何在该类型的实例上使用GetEnumName? 我创建了一个小型演示类来说明问题: 键入 TEnumSettings&TK;记录> = class private 键:TKey; public 构造函数Create(aKey:TKey); 函数ToString:string;覆盖结束 使用 TypInfo; {TEnumSettings< TKey> } 构造函数TEnumSettings< TKey> .Create(aKey:TKey); begin 如果PTypeInfo(System.TypeInfo(TKey)).Gind<> tkEnumeration then Exception.Create(string(PTypeInfo(System.TypeInfo(TKey))。Name)+'不是枚举'); 密钥:= aKey; 结束 函数TEnumSettings< TKey> .ToString:string; begin 结果:= GetEnumName(System.TypeInfo(TKey),Integer(Key))< ==这里我得到一个编译错误:无效的类型cast end; 我使用的是Delphi XE。那么这可以做到吗如果是这样呢?解决方案个人来说,我会通过调用 Move 。我有以下类型: type TEnumeration< T:record> = class strict private class function TypeInfo:PTypeInfo;一致;静态的; 类函数TypeData:PTypeData;一致;静态的; public 类函数IsEnumeration:Boolean;静态的; 类函数ToOrdinal(枚举:T):整数;一致;静态的; 类函数FromOrdinal(Value:Integer):T;一致;静态的; 类函数MinValue:Integer;一致;静态的; 类函数MaxValue:Integer;一致;静态的; 类函数InRange(Value:Integer):Boolean;一致;静态的; 类函数EnsureRange(Value:Integer):Integer;一致;静态的; 结束 {TEnumeration< T> } 类函数TEnumeration< T> .TypeInfo:PTypeInfo; begin 结果:= System.TypeInfo(T); 结束 类函数TEnumeration< T> .TypeData:PTypeData; begin 结果:= TypInfo.GetTypeData(TypeInfo); 结束 类函数TEnumeration< T> .IsEnumeration:Boolean; begin 结果:= TypeInfo.Kind = tkEnumeration; 结束 类函数TEnumeration< T> .ToOrdinal(枚举:T):整数; begin Assert(IsEnumeration); Assert(SizeOf(Enum)< = SizeOf(Result)); 结果:= 0; //当SizeOf(Enum) Move(枚举,结果,SizeOf(枚举)); Assert(InRange(Result)); 结束 类函数TEnumeration< T> .FromOrdinal(Value:Integer):T; begin Assert(IsEnumeration); Assert(InRange(Value)); Assert(SizeOf(Result)< = SizeOf(Value)); Move(Value,Result,SizeOf(Result)); 结束 类函数TEnumeration< T> .MinValue:Integer; begin Assert(IsEnumeration); 结果:= TypeData.MinValue; 结束 class function TEnumeration< T> .MaxValue:Integer; begin Assert(IsEnumeration); 结果:= TypeData.MaxValue; 结束 类函数TEnumeration< T> .InRange(Value:Integer):Boolean; var ptd:PTypeData; begin Assert(IsEnumeration); ptd:= TypeData; 结果:= Math.InRange(Value,ptd.MinValue,ptd.MaxValue); 结束 类函数TEnumeration< T> .EnsureRange(Value:Integer):整数; var ptd:PTypeData; begin Assert(IsEnumeration); ptd:= TypeData; 结果:= Math.EnsureRange(Value,ptd.MinValue,ptd.MaxValue); 结束 ToOrdinal 我确定你可以适应你的班级。 如果你不喜欢使用 Move 这样,那么你可以使用 TValue 。 TValue.From< TKey>(Key).AsOrdinal 而@TLama指出你可以避免调用 GetEnumName 根据使用 TValue.From< TKey> ).ToString 面对它,使用 TValue 似乎更符合泛型和RTTI的精神。调用 Move 依赖于枚举类型的具体实现细节。但是,通过调试器来查看执行 TValue.From< TKey>(Key).AsOrdinal 之间的代码是非常有趣的。这一点就足以令我犹豫,推荐使用 TValue 。 另一种实现此目的的方法是使用 TRttiEnumerationType : TRttiEnumerationType.GetName< TKey>(Key) 执行此操作比使用 TValue.ToString 更有效,只是调用 GetEnumName 。 I have a Generic class wich uses an Enum Generic Type. My problem how do I use GetEnumName on an instance of that type ?I've created a small demo class to illustrate the problem :type TEnumSettings<TKey: record > = class private Key: TKey; public constructor Create(aKey: TKey); function ToString: string; override; end;uses TypInfo;{ TEnumSettings<TKey> }constructor TEnumSettings<TKey>.Create(aKey: TKey);begin if PTypeInfo(System.TypeInfo(TKey)).Kind <> tkEnumeration then Exception.Create(string(PTypeInfo(System.TypeInfo(TKey)).Name) + ' is not an Enumeration'); Key := aKey;end;function TEnumSettings<TKey>.ToString: string;begin Result := GetEnumName(System.TypeInfo(TKey), Integer(Key)) <== HERE I get a compile error: Invalid type castend;I'm using Delphi XE. So can this be done? And if so how? 解决方案 Personally, I would do this with a call to Move. I have the following type:type TEnumeration<T: record> = class strict private class function TypeInfo: PTypeInfo; inline; static; class function TypeData: PTypeData; inline; static; public class function IsEnumeration: Boolean; static; class function ToOrdinal(Enum: T): Integer; inline; static; class function FromOrdinal(Value: Integer): T; inline; static; class function MinValue: Integer; inline; static; class function MaxValue: Integer; inline; static; class function InRange(Value: Integer): Boolean; inline; static; class function EnsureRange(Value: Integer): Integer; inline; static; end;{ TEnumeration<T> }class function TEnumeration<T>.TypeInfo: PTypeInfo;begin Result := System.TypeInfo(T);end;class function TEnumeration<T>.TypeData: PTypeData;begin Result := TypInfo.GetTypeData(TypeInfo);end;class function TEnumeration<T>.IsEnumeration: Boolean;begin Result := TypeInfo.Kind=tkEnumeration;end;class function TEnumeration<T>.ToOrdinal(Enum: T): Integer;begin Assert(IsEnumeration); Assert(SizeOf(Enum)<=SizeOf(Result)); Result := 0; // needed when SizeOf(Enum) < SizeOf(Result) Move(Enum, Result, SizeOf(Enum)); Assert(InRange(Result));end;class function TEnumeration<T>.FromOrdinal(Value: Integer): T;begin Assert(IsEnumeration); Assert(InRange(Value)); Assert(SizeOf(Result)<=SizeOf(Value)); Move(Value, Result, SizeOf(Result));end;class function TEnumeration<T>.MinValue: Integer;begin Assert(IsEnumeration); Result := TypeData.MinValue;end;class function TEnumeration<T>.MaxValue: Integer;begin Assert(IsEnumeration); Result := TypeData.MaxValue;end;class function TEnumeration<T>.InRange(Value: Integer): Boolean;var ptd: PTypeData;begin Assert(IsEnumeration); ptd := TypeData; Result := Math.InRange(Value, ptd.MinValue, ptd.MaxValue);end;class function TEnumeration<T>.EnsureRange(Value: Integer): Integer;var ptd: PTypeData;begin Assert(IsEnumeration); ptd := TypeData; Result := Math.EnsureRange(Value, ptd.MinValue, ptd.MaxValue);end;The ToOrdinal method does what you need, and I'm sure you'll be able to adapt it to your class.If you don't like using Move in this way, then you can use TValue.TValue.From<TKey>(Key).AsOrdinalAnd @TLama points out that you can avoid calling GetEnumName at all by usingTValue.From<TKey>(Key).ToStringOn the face of it, using TValue seems to be more in keeping with the ethos of generics and RTTI. A call to Move relies on the specific implementation details of enumerated types. However, it's quite interesting to step through the debugger and observe quite how much code is involved in executing TValue.From<TKey>(Key).AsOrdinal. That alone is enough to make me hesitate to recommend using TValue.Yet another way to achieve this is to use TRttiEnumerationType:TRttiEnumerationType.GetName<TKey>(Key)The implementation of this is much more efficient than using TValue.ToString, being little more than a call to GetEnumName. 这篇关于如何使用通用枚举类型调用GetEnumName?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!
09-27 00:37