Generic functions for converting an enumeration to string and back

后端 未结 5 1760
终归单人心
终归单人心 2020-12-11 01:33

I\'m trying to write functions that will convert an enumeration to string and back again.

ie:

TConversions = class
    strict private
    public
            


        
5条回答
  •  没有蜡笔的小新
    2020-12-11 01:45

    I'd offer the following variant, a simple extension of the code from my answer to a similar question: How can I call GetEnumName with a generic enumerated type?

    type
      TEnumeration = 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 ToString(Enum: T): string; inline; static;
        class function FromString(const S: string): 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 }
    
    class function TEnumeration.TypeInfo: PTypeInfo;
    begin
      Result := System.TypeInfo(T);
    end;
    
    class function TEnumeration.TypeData: PTypeData;
    begin
      Result := TypInfo.GetTypeData(TypeInfo);
    end;
    
    class function TEnumeration.IsEnumeration: Boolean;
    begin
      Result := TypeInfo.Kind=tkEnumeration;
    end;
    
    class function TEnumeration.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.FromOrdinal(Value: Integer): T;
    begin
      Assert(IsEnumeration);
      Assert(InRange(Value));
      Assert(SizeOf(Result)<=SizeOf(Value));
      Move(Value, Result, SizeOf(Result));
    end;
    
    class function TEnumeration.ToString(Enum: T): string;
    begin
      Result := GetEnumName(TypeInfo, ToOrdinal(Enum));
    end;
    
    class function TEnumeration.FromString(const S: string): T;
    begin
      Result := FromOrdinal(GetEnumValue(TypeInfo, S));
    end;
    
    class function TEnumeration.MinValue: Integer;
    begin
      Assert(IsEnumeration);
      Result := TypeData.MinValue;
    end;
    
    class function TEnumeration.MaxValue: Integer;
    begin
      Assert(IsEnumeration);
      Result := TypeData.MaxValue;
    end;
    
    class function TEnumeration.InRange(Value: Integer): Boolean;
    var
      ptd: PTypeData;
    begin
      Assert(IsEnumeration);
      ptd := TypeData;
      Result := Math.InRange(Value, ptd.MinValue, ptd.MaxValue);
    end;
    
    class function TEnumeration.EnsureRange(Value: Integer): Integer;
    var
      ptd: PTypeData;
    begin
      Assert(IsEnumeration);
      ptd := TypeData;
      Result := Math.EnsureRange(Value, ptd.MinValue, ptd.MaxValue);
    end;
    

    I typed it on my phone so it might need work to compile. It offers what you ask for and more.

    One key thing that this variant does is to separate the conversion between enum and ordinal into re-usable methods.

提交回复
热议问题