我有一个方法需要返回一个对象.当然,只有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,你会看到实际发生的事情.
奖金阅读
> Delphi: determine actual type of a generic?
> Conditional behaviour based on concrete type for generic class
回答
我会让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;