5

我正在尝试创建一个通用类,我可以使用一组枚举来启动其中的值。例如:

constructor TManager<TEnum>.Create;
var
  enum: TEnum;
  enumObj: TMyObject;
begin
  fMyObjectList:=  TObjectDictionary<TEnum,TMyObject>.Create([doOwnsValues],10);
  for enum:= Low(TEnum) to High(TEnum) do
  begin
    enumObj:= TMyObject.Create();
    fMyObjectList.Add(enum, enumObj);
  end;
end;

此外,后面的方法将通过枚举值获取对象,例如:

function TManager<TEnum>.Fetch(enum: TEnum): TMyObject;
begin
  fMyObjectList.TryGetValue(enum, Result);
end;

但是,作为通用参数传递,delphi 并不知道 TEnum 将是一个枚举。我可以以某种方式强制执行吗?

4

2 回答 2

7

正如大卫所说,你能做的最好的事情就是在运行时使用 RTTI。

    type  
      TRttiHelp = record
        class procedure EnumIter<TEnum {:enum}>; static;
      end;

    class procedure TRttiHelp.EnumIter<TEnum {:enum}>;
    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;  

虽然我不知道当您的枚举定义了值时代码的行为,例如

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

编辑:

如果您想返回iterValue枚举,可以使用以下函数,该函数取自Jim Ferguson 的枚举助手类

class function TRttiHelp.EnumValue<TEnum {:enum}>(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;

然后,您可以使用一般提供的作为构造函数中字典的索引。

于 2012-09-12T07:09:52.437 回答
2

您不能约束一个泛型参数,这样low()并且high()可以在泛型类中使用。唯一可用的约束是类或接口约束。

据我所知,该语言没有提供通用方法来枚举通用枚举类型。可能你能做的最好的事情就是使用 RTTI,牺牲编译时类型的安全性(如 Tobias 所示)。


阅读了对 Tobias 答案的评论后,您似乎真正想要的是 TObjectDictionary<TEnum,TMyObject>. 那是因为您希望能够找到TMyObject给定TEnum密钥的实例。你想要TObjectDictionary而不是TDictionary因为前者接管了TMyObject实例的所有权。完成后,您需要有人将它们全部释放,您不妨让TObjectDictionary它们为您完成。

有关所有权方面的示例,请参阅@RRUZ 在此处的答案:使用 Generics.Collections.TObjectDictionary 的示例

于 2012-09-12T06:20:50.257 回答