Можно ли преобразовать значение типа <T>в Variant? - PullRequest
6 голосов
/ 25 октября 2011

Вот фрагмент, показывающий, чего я пытаюсь достичь:

type
  TMyObject<T> = class (TObject)
    function GetVarType(Value: T): TVarType;
  end;


function TMyObject<T>.GetVarType(Value: T): TVarType;
var
  TmpValue: Variant;
begin
  TmpValue := Variant(Value); //Invalid typecast
  Result := VarType(TmpValue);
end;

Я знаю, что вышеизложенное с typecast наивно, но я надеюсь, что вы поняли. Я хотел бы заменить его некоторым механизмом преобразования.

TMyObject всегда будет иметь простой тип, такой как Integer, String, Single, Double.

Целью такого преобразования является то, что функция VarType дает мне целочисленную константу для каждого простого типа, которую я могу хранить где-то еще.

Я хотел бы знать, возможно ли такое преобразование?

Спасибо за ваше время.

Ответы [ 4 ]

7 голосов
/ 26 октября 2011

Это легко решается в Delphis с улучшенным RTTI (2010 и новее).Жаль, что вы ограничены 2009 годом: (

function TMyObject<T>.GetVarType(Value: T): TVarType;
begin
  Result := VarType(TValue.From<T>(Value).AsVariant);
end;

Это работает только для простых типов, но это было ограничение, указанное в вопросе.

6 голосов
/ 25 октября 2011

Вы можете использовать RTTI для получения этой информации, просто проверьте значение свойства TTypeInfo.Kind:

Проверьте этот пример кода

{$APPTYPE CONSOLE}

uses
  TypInfo,
  Variants,
  Generics.Collections,
  SysUtils;

type
  TMyObject<T> = class (TObject)
    function GetVarType(Value: T): TVarType;
  end;


function TMyObject<T>.GetVarType(Value: T): TVarType;
begin
  Case PTypeInfo(TypeInfo(T))^.Kind of
    tkInteger : Result:=varInteger;
    tkFloat   : Result:=varDouble;
    tkString  : Result:=varString;
    tkUString : Result:=varUString;
    //add more types here
  End;
end;

Var
  LObj : TMyObject<Integer>;
begin
  try
     Writeln(VarTypeAsText(TMyObject<Integer>.Create.GetVarType(5)));
     Writeln(VarTypeAsText(TMyObject<String>.Create.GetVarType('Test')));
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  Readln;
end.

это вернет

Integer
UnicodeString
1 голос
/ 25 октября 2011

Спасибо, ребята, за ваши ответы:

Как показала @RRUZ, это возможно (я имею в виду не строгое присвоение, а извлечение типа данных). Я работал сам, ожидая ответа, и нашел более общее решение.

Итак, я задаю это здесь:

type
  TMyObject<T> = class (TObject)
    function GetVarType(Value: T): TVarType;
  end;


function TMyObject<T>.GetVarType(Value: T): TVarType;
begin
  Result := GetTypeData(TypeInfo(T)).varType;
end;

Еще раз спасибо!

1 голос
/ 25 октября 2011

Я не понимаю, как можно сделать это с помощью дженериков.Компилятор должен знать, что экземпляр типа T может быть назначен на Variant для любого возможного T.Вы не можете сказать этому компилятору, что это возможно.

Если бы это были шаблоны, как в C ++, то это было бы тривиально.

...