我有一个方法需要返回一个对象.当然,只有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;
Run Code Online (Sandbox Code Playgroud)
如果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;
Run Code Online (Sandbox Code Playgroud)
我看到两个主要选择。如果泛型类型必须是类类型,并且这是在编译时知道的,则应该对该类型应用约束:
type
TGrobber<T: class> = class
....
end;
Run Code Online (Sandbox Code Playgroud)
或者,如果类型必须派生自特定类,则可以像这样指定该约束:
type
TGrobber<T: TMyObject> = class
....
end;
Run Code Online (Sandbox Code Playgroud)
应用约束后,您只需要直接分配即可。
Result := current;
Run Code Online (Sandbox Code Playgroud)
这是可能的,因为编译器强制对泛型类型进行约束。因此知道该分配对于所有可能的实例化都是有效的。
我想说的是,泛型类有一个返回的函数似乎很奇怪TObject。为什么你的函数不返回T?
如果您无法约束,那么简单的指针类型转换是最干净的方法:
Result := PObject(@current)^;
Run Code Online (Sandbox Code Playgroud)
显然,您需要检查它T是一个类类型,即您已经掌握的代码。
就其价值而言,从 Delphi XE7 开始,使用以下命令检查类型的种类更加简单System.GetTypeKind:
if GetTypeKind(T) = tkClass then
Result := PObject(@current)^
else
Result := nil;
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2497 次 |
| 最近记录: |