Delphi 如何将通用T转换为TObject?

Delphi 如何将通用T转换为TObject?,delphi,generics,Delphi,Generics,我有一个方法需要返回一个对象。当然,只有当T是一个对象时,它才有意义: function TGrobber<T>.Swipe: TObject; var current: T; begin { If generic T is not an object, then there's nothing we can return But we'll do the caller a favor and not crash horribly.

我有一个方法需要返回一个对象。当然,只有当
T
是一个对象时,它才有意义:

function TGrobber<T>.Swipe: TObject;
var
   current: T;
begin
    {
       If generic T is not an object, then there's nothing we can return
       But we'll do the caller a favor and not crash horribly.
    }
    if PTypeInfo(TypeInfo(T))^.Kind <> tkClass then
    begin
       Result := nil;
       Exit;
    end;

    //We *are* an object, return the object that we are.
    current := Self.SwipeT;

    Result := TObject(current); <--E2089 invalid class typecast
end;

是的,可以通过TValue完成,但这不是正确的方法。我认为最好让编译器验证它是一个TObject(或后代)

unitgrobberu;
接口
类型
TGrobber=类
公众的
功能滑动:TObject;
结束;
实施
{tgrober}
函数tgrobider.swip:TObject;
开始
结果:=T;
结束;
结束。
然后您可以测试它:

procedure TForm37.FormCreate(Sender: TObject);
var
  Grobber1 : TGrobber<TEdit>;
  Grobber2 : TGrobber<Integer>; <-- Does not compile    
begin
end;
程序TForm37.FormCreate(发送方:TObject);
变量
Grobber1:TGrobber;

Grobber2:TGrobber 我看到两个主要的选择。如果泛型类型必须是类类型,并且在编译时知道这一点,则应该对该类型应用约束:

type
  TGrobber<T: class> = class
    ....
  end;
这是可能的,因为编译器对泛型类型强制执行约束。因此知道赋值对所有可能的实例化都有效

我要说的是,泛型类有一个返回
TObject
的函数似乎有些奇怪。为什么函数不返回
t

如果无法约束,则简单指针类型转换是最干净的方法:

Result := PObject(@current)^;
显然,您需要检查
T
是否是一种类类型,您已经演示了对该类的掌握程度

由于Delphi XE7,因此使用
System.GetTypeKind
检查类型更为简单:

if GetTypeKind(T) = tkClass then
  Result := PObject(@current)^
else
  Result := nil;

@我测试了这个概念。代码
Result:=TObject(字节(7))编译并运行。这可能是等待中的访问冲突。幸运的是,由于我的先决条件,我不会将
字节
强制转换为
对象
。可能是
TValue.From(current).AsObject
?@TLama哇,
TValue
助手记录解决了所有问题。复制/粘贴我为奖励您的声誉而添加到问题中的答案。@Guillem TValue是重量级的,不适合此任务。要么在编译时进行约束,要么使用类似于:
Result:=PObject(@current)^
@Guillem TValue有它的位置,它通常作为RTTI方法参数的管道
Result:=T
不会编译,因为
T
是一个类型而不是实例。此外,不需要截图来显示编译器错误。编译器错误是文本。它们可以简单地一字不差地粘贴为文本。您在@DavidHeffernan中正确地看到了Swipe的返回值a hould of cause be Result:=Swipe。但是它确实编译了。不,它不编译。[dcc32错误]E2010不兼容的类型:“TObject”和“T”那么让我更准确地说:在Delphi Xe中,它确实存在,这是一个编译器错误。我不明白你为什么坚持这样做。
TValue
与你的代码做同样的事情(将指针投射到TObject以阻止键入)。虽然to在
期间从
计算了一些额外的内容。另一方面,在运行时使用规范的
TValue
typing helper记录来查询和操作泛型类型有其优点。@IanBoyd我不相信这就是
TValue
的目的。然而,如果你愿意,你显然可以这样做。就我个人而言,我会按照上面写的方式来做,但这两种方式都不会让我感到太激动。而且,我的Delphi版本中不存在
GetTypeKind
。我们又来了。是的,它在XE7中似乎是新的。我想你的代码现在胜出了。
type
  TGrobber<T: TMyObject> = class
    ....
  end;
Result := current;
Result := PObject(@current)^;
if GetTypeKind(T) = tkClass then
  Result := PObject(@current)^
else
  Result := nil;