程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> Delphi >> 用泛型實現對枚舉的通用處理,泛型枚舉通用

用泛型實現對枚舉的通用處理,泛型枚舉通用

編輯:Delphi

用泛型實現對枚舉的通用處理,泛型枚舉通用


寫代碼的時候遇到一個問題,想寫一個通用方法來實現對枚舉的類型的操作,如獲取枚舉的項的列表,獲取一個枚舉值的索引等等,

本來以為很簡單,寫一個函數:

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;

implementation

uses
  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;

 

通過這次嘗試,加深了對泛型的理解。


C#怎限定泛型類型T一定是一個枚舉類型?

其實錯誤消息已經很明確的告訴你了,A type used as a constraint must be an interface, a non-sealed class or a type parameter.
必須是接口、未封閉的類或者類型
所以枚舉是不行的,你說說你到底想要實現什麼功能,我幫你想想辦法
 

對於泛型方法中,參數為枚舉類型,怎取到該枚舉所屬類型的值?

public static IEnumerable<OT> GetByte<OT, T>() where T : OT { var t = typeof(T); T[] value = Enum.GetValues(t) as T[]; List<OT> aa = value.Select(j => (OT)j).ToList(); return aa; }
 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved