简体   繁体   English

如何在 Delphi 中将特定类型的变量转换为泛型 T?

[英]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;根据T的实际类型,我想返回一个特定的值; 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 ...很明显,我不能将T以外的任何东西分配给Result ,并且as TT()不起作用,当T不限于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;

I believe this is the best method (performance-wise at least) to achieve what you want.我相信这是实现您想要的最佳方法(至少在性能方面)。

type 
  PMyObject = ^TMyObject;

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

The only way I found is using System.Rtti.TValue (exception if wrong type):我发现的唯一方法是使用System.Rtti.TValue (如果类型错误则例外):

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):或更短的 ;-) 自动类型(如果类型错误,则返回 false;您可以在此处忽略它,因为您已经检查了 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.有人担心泛型可能不是一个好的解决方案,但我们无法在不了解更多背景的情况下判断。

I'm using Delphi XE5.我正在使用 Delphi XE5。

Change yoru sample to this:将 yoru 示例更改为:

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

The change is TMyObject to class .更改是TMyObjectclass When you are not "class" it, you will get the compiler error E2089.当你没有“类”它时,你会得到编译器错误 E2089。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM