Using an enum with generics

后端 未结 2 1048
太阳男子
太阳男子 2021-01-06 02:40

I\'m trying to create a generic class to which I can use a set of enums to initiate the values inside. For example:

constructor TManager.Create         


        
2条回答
  •  孤城傲影
    2021-01-06 02:56

    As David mentioned the best you can do is at runtime with RTTI.

        type  
          TRttiHelp = record
            class procedure EnumIter; static;
          end;
    
        class procedure TRttiHelp.EnumIter;
        var
          typeInf: PTypeInfo;
          typeData: PTypeData;
          iterValue: Integer;
        begin
          typeInf := PTypeInfo(TypeInfo(TEnum));
          if typeInf^.Kind <> tkEnumeration then
            raise EInvalidCast.CreateRes(@SInvalidCast);
    
          typeData := GetTypeData(typeInf);
          for iterValue := typeData.MinValue to typeData.MaxValue do
            WhateverYouWish;
        end;  
    

    Although I don't know how the code behaves when your enum has defined values such as

        (a=9, b=19, c=25)
    

    Edit:

    If you would like to return iterValue to the enum, you may use the following function, taken from a enum helper class by Jim Ferguson

    class function TRttiHelp.EnumValue(const aValue: Integer): TEnum;
    var
      typeInf: PTypeInfo;
    begin
      typeInf := PTypeInfo(TypeInfo(TEnum));
      if typeInf^.Kind <> tkEnumeration then
        raise EInvalidCast.CreateRes(@SInvalidCast);
    
      case GetTypeData(typeInf)^.OrdType of
        otUByte, otSByte:
          PByte(@Result)^ := aValue;
        otUWord, otSWord:
          PWord(@Result)^ := aValue;
        otULong, otSLong:
          PInteger(@Result)^ := aValue;
      else
        raise EInvalidCast.CreateRes(@SInvalidCast);
      end;
    end;
    

    You may then use the generically provided as the index to the dictionary in your constructor.

提交回复
热议问题