首页 > 代码库 > 用泛型实现对枚举的通用处理

用泛型实现对枚举的通用处理

写代码的时候遇到一个问题,想写一个通用方法来实现对枚举的类型的操作,如获取枚举的项的列表,获取一个枚举值的索引等等,

本来以为很简单,写一个函数:

function GetEnumNames(枚举类): TArray<string>

结果发现这个参数怎么搞也搞不对,不知道传一个什么样的参数可以支持所有枚举类型,因为函数内会用TypeInfo。

后来想到用泛型来传入枚举类来处理,果然成功了。

  /// <summary> 针对枚举类型的一组功能函数 </summary>  TEnumEX<T> = class  public    /// <summary> 把字符串转成枚举的值 </summary>    class function StrToEnumType(const S: string): T; overload;    /// <summary> 把字符串转成枚举的值 </summary>    class function StrToEnumType(const S: string; Default: T): T; overload;    /// <summary> 把枚举的值转成字符串 </summary>    class function EnumToString(Value: T): string;    /// <summary> 获取枚举类型的项列表 </summary>    class function GetEnumNames : TArray<string>;    /// <summary> 获取枚举值的序号 </summary>    class function GetEnumOrd(const S: string) : Integer;  end;implementationuses  RTTI,SysConst,uLayoutConst;{ TEnumConvert<T> }class function TEnumEX<T>.EnumToString(Value: T): string;var  v: Integer;begin  case PTypeInfo(TypeInfo(T))^.Kind of    tkEnumeration:      case TypInfo.GetTypeData(TypeInfo(T))^.OrdType of        otUByte, otSByte: v := PByte(@Value)^;        otUWord, otSWord: v := PWord(@Value)^;        otULong, otSLong: v := PInteger(@Value)^;      end;  else    raise EInvalidCast.CreateRes(@SInvalidCast);  end;  Result := TypInfo.GetEnumName(TypeInfo(T), v);end;class function TEnumEX<T>.StrToEnumType(const S: string): T;begin  case PTypeInfo(TypeInfo(T))^.Kind of    tkEnumeration:      case TypInfo.GetTypeData(TypeInfo(T))^.OrdType of        otUByte, otSByte: PByte(@Result)^ := GetEnumValue(TypeInfo(T), S);        otUWord, otSWord: PWord(@Result)^ := GetEnumValue(TypeInfo(T), S);        otULong, otSLong: PInteger(@Result)^ := GetEnumValue(TypeInfo(T), S);      end;  else    raise EInvalidCast.CreateRes(@SInvalidCast);  end;end;class function TEnumEX<T>.GetEnumNames: TArray<string>;var  p: PTypeData;  i: Integer;  s: String;  pt: PTypeInfo;begin  pt := TypeInfo(T);  p := GetTypeData(TypeInfo(T));  SetLength(Result, p.MaxValue+1);  for i := p.MinValue to p.MaxValue do  begin    S := GetEnumName(pt,i);    Result[i] := S;  end;end;class function TEnumEX<T>.GetEnumOrd(const S: string): Integer;begin  case PTypeInfo(TypeInfo(T))^.Kind of    tkEnumeration:        Result := GetEnumValue(TypeInfo(T), S);  else    raise EInvalidCast.CreateRes(@SInvalidCast);  end;end;class function TEnumEX<T>.StrToEnumType(const S: string; Default: T): T;begin  if S <> ‘‘ then begin    Result := StrToEnumType(S);  end else begin    Result := Default;  end;end;

 

调用很简单

var  s : string;  ss : TArray<string>;begin  inherited;  ss := TEnumEX<TBIEditUIControl>.GetEnumNames;  for s in ss do  begin    ShowMessage(s);  end;end;

 

通过这次尝试,加深了对泛型的理解。

用泛型实现对枚举的通用处理