Search code examples
delphigenericscastingtype-conversiondelphi-10.2-tokyo

How to cast a variable of specific type to generic T in Delphi?


Depending on the actual type of T, I want to return a specific value; here a simplified example (a record wrapper around some object):

function TMyRec.TryGet<T>(const Default: T): T;
begin
  if TypeInfo(T) = TypeInfo(TMyObject) then
    Result:= FMyObject {E2010 Incompatible types}
  else Result:= FMyObject.TryGet<T>(Default);
end;

It's clear that I cannot assign anything other than T to Result, and as T or T() don't work, when T is not restricted to class...

It's also not possible to do an overload which differs only in the generic restriction:

function TryGet<T: TMyObject>(const Default: T): T; overload;
{...}
Result:= FMyObject as T; {here it would work}

To help understand the discussion in the comments below, here is the example from before my edit:

function TMyRec.TryGet<T>(const Default: T): T;
begin
  if TypeInfo(T) = TypeInfo(TMyObject) then Result:= FMyObject
  //else ...
  else Result:= Default;
end;

Solution

  • The only way I found is using System.Rtti.TValue (exception if wrong type):

    Result:= TValue.From(FMyObject).AsType<T>
    

    or much shorter ;-) with automatic type (returns false if wrong type; you could ignore that here because you already checked TypeInfo):

    TValue.From(FMyObject).TryAsType(Result)
    

    Suggestion: rethink your concept; there are concerns that generics might not be a good solution, but we cannot tell without knowing more about the background.