[英]How to cast generic T to a TObject?
我有一个方法需要返回一个对象。 当然,只有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;
如果T
不是对象(例如Integer
, String
或OleVariant
),则它将返回nil
,并且不会严重崩溃。
如果我们是一个对象(例如TCustomer
, TPatron
, TSalesOrder
, TShape
),那么我们可以很好地返回该对象。
我不想混淆这个问题。 但是,如果您查看IEnumerable
,则会看到实际情况。
我将让TLama复制/粘贴答案以得到他的荣誉:
function TGrobber<T>.Swipe: TObject;
var
current: T;
v: TValue;
begin
current := Self.SwipeT;
v := TValue.From<T>(current);
{
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 not v.IsObject then
begin
Result := nil;
Exit;
end;
Result := v.AsObject;
end;
我看到两个主要选项。 如果泛型类型必须是类类型,并且在编译时就知道了,则应将约束应用于该类型:
type
TGrobber<T: class> = class
....
end;
或者,如果类型必须从特定的类派生,则可以这样指定约束:
type
TGrobber<T: TMyObject> = class
....
end;
一旦应用了约束,那么您就需要直接分配。
Result := current;
这是可能的,因为编译器会对您的泛型类型施加约束。 因此知道该分配对所有可能的实例均有效。
我要评论的是,泛型类具有返回TObject
的函数似乎很奇怪。 您的函数为什么不返回T
?
如果您不能约束,那么简单的指针类型转换是最干净的方法:
Result := PObject(@current)^;
显然,您需要检查T
是一个类类型,您已经证明了它是熟练的代码。
值得一提的是,由于使用Delphi XE7,使用System.GetTypeKind
检查类型的类型更加简单:
if GetTypeKind(T) = tkClass then
Result := PObject(@current)^
else
Result := nil;
是的,可以通过TValue完成,但这不是正确的方法。 我相信让编译器验证它是TObject(或后代)要好得多。
unit GrobberU;
interface
type
TGrobber<T : Class> = class
public
function Swipe: TObject;
end;
implementation
{ TGrobber<T> }
function TGrobber<T>.Swipe: TObject;
begin
Result := T;
end;
end.
然后您可以测试它:
procedure TForm37.FormCreate(Sender: TObject);
var
Grobber1 : TGrobber<TEdit>;
Grobber2 : TGrobber<Integer>; <-- Does not compile
begin
end;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.