Delphi 如何使用类型为的类的泛型帮助器

Delphi 如何使用类型为的类的泛型帮助器,delphi,generics,delphi-xe6,Delphi,Generics,Delphi Xe6,我正在试图弄清楚如何泛化这个helper方法;因此,它将返回请求的相同类型: type TScreenHelper = class helper for TScreen public function FindForm(DesiredFormClass: TFormClass): TForm; end; 现在,调用者必须将返回值强制转换为他们已经想要的类型: var frmReportReminderSetup: TfrmReportReminde

我正在试图弄清楚如何泛化这个helper方法;因此,它将返回请求的相同类型:

type
    TScreenHelper = class helper for TScreen
    public
        function FindForm(DesiredFormClass: TFormClass): TForm;
    end;
现在,调用者必须将返回值强制转换为他们已经想要的类型:

var
   frmReportReminderSetup: TfrmReportReminderSetup;
begin
   //frmReportReminderSetup := Screen.FindForm(TfrmReportReminderSetup); Doesn't compile

   frmReportReminderSetup := TfrmReportReminderSetup(Screen.FindForm(TfrmReportReminderSetup));
非通用实现是:

function TScreenHelper.FindForm(DesiredFormClass: TFormClass): TForm;
var
    f: TForm;
    i: Integer;
begin
    Result := nil;

    for i := 0 to Screen.FormCount-1 do //Screen.Forms does not support enumeration
    begin
        f := Screen.Forms[i];

        if (f is DesiredFormClass) then
        begin
            Result := f;
            Exit;
        end;
    end;
end;
仿制药 我想要的是某种使用泛型的方法,以便函数返回它要求的类型

frmContoso := Screen.FindForm(TfrmContoso);
在伪代码中,我想要的签名类似于:

function FindForm(T: TFormClass): T;
当需要将其转换为实际的Delphi语法时,我认为您必须在尖括号中指定一个T引用:

function FindForm(<T>): T;
我能看出有什么不对劲。它不理解t是一个类(即,如果它是一个
Integer
,那么将其设置为
nil将是绝对错误的)

约束条件 因此,我需要以某种方式向编译器提示
T
将是什么类型:

TScreenHelper = class helper for TScreen
public
    function FindForm<T: TFormClass>: T;
end;

function TScreenHelper.FindForm<T: TFormClass>: T;
var
    f: TForm;
    i: Integer;
begin
    Result := nil;

    for i := 0 to Screen.FormCount-1 do //Screen.Forms does not support enumeration
    begin
        f := Screen.Forms[i];

        if (f is T) then
        begin
            Result := f as T;
            Exit;
        end;
    end;
end;
示例非工作代码
程序项目2;
{$APPTYPE控制台}
{$R*.res}
使用
System.SysUtils、Vcl.Forms;
类型
TScreenHelperCore=类(ToObject)
公众的
类函数FindForm:T;
结束;
TfrmContoso=类(TForm)
公众的
结束;
{TScreenHelperCore}
类函数TScreenHelperCore.FindForm:T;
//\\\\[dcc32错误]项目2.dpr(23):E2029',',';'或应为“>”但找到“:”
变量
f:TForm;
i:整数;
开始
结果:=无;
对于i:=0到Screen.FormCount-1 do//Screen.Forms不支持枚举
开始
f:=屏幕表格[i];
如果(f)是T,那么
开始
结果:=f;
出口
结束;
结束;
结束;
变量
f:TfrmContoso;
开始
尝试
f:=TScreenHelperCore.FindForm;
如果f=nil,则
f:=TfrmContoso.Create(nil);
f、 ShowModal;
除了
关于E:Exception-do
Writeln(E.ClassName,“:”,E.Message);
结束;
结束。

您的约束是错误的。而不是

function FindForm<T: TFormClass>: T;

你确定这是正确的语法吗?我得到了
E2029',',';'或“>”应为,但“:”在
T:
的中间找到。另外,如果
T
被限制为类型
TForm
,那么我不需要在XE7中编译类型
TForm
。我接受约束部分中的代码,并将TFormClass更改为TForm。并移除实现中的约束。无需重复。我已更新了问题,以包含一个完整的非功能性控制台测试应用程序。你能给我看一下你的代码吗,这样我们就可以比较一下为什么你的代码不能编译了?是的,你说在助手中不可能有泛型。所以我消除了无关的困惑。如果愿意,我可以从helper类
TScreenHelper
包装对
TScreenHelper核心的调用。我也可以删除这个问题,然后再问一次,除非删除对“helper”的引用可以严格关注“泛型”问题。我知道什么?!你需要找一个真正的专家。伊恩@XE6!?D5怎么了?;)我只看了3-4页就知道是谁写了这个问题:)@NGLN跟上时代。我们继续前进@LURD的确如此。我从我手机的第一页就知道了@我的雇主决定花3000美元买一个新版本。三个月后,错误百出的升级已经过时:(
Result := nil;  E2010 Incompatible types: 'T' and 'Pointer'
TScreenHelper = class helper for TScreen
public
    function FindForm<T: TFormClass>: T;
end;

function TScreenHelper.FindForm<T: TFormClass>: T;
var
    f: TForm;
    i: Integer;
begin
    Result := nil;

    for i := 0 to Screen.FormCount-1 do //Screen.Forms does not support enumeration
    begin
        f := Screen.Forms[i];

        if (f is T) then
        begin
            Result := f as T;
            Exit;
        end;
    end;
end;
frmContoso := Screen.FindForm<TfrmConsoto>();
function FindForm<T: TFormClass>: T;
function FindForm(DesiredFormClass: TFormClass): TForm;
program Project2;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils, Vcl.Forms;

type
    TScreenHelperCore = class(TObject)
    public
        class function FindForm<T: TForm>: T;
    end;

    TfrmContoso = class(TForm)
    public

   end;

{ TScreenHelperCore }

class function TScreenHelperCore.FindForm<T: TForm>: T; 
//                                         \__[dcc32 Error] Project2.dpr(23): E2029 ',', ';' or '>' expected but ':' found
var
    f: TForm;
    i: Integer;
begin
    Result := nil;

    for i := 0 to Screen.FormCount-1 do //Screen.Forms does not support enumeration
    begin
        f := Screen.Forms[i];

        if (f is T) then
        begin
            Result := f;
            Exit;
        end;
    end;
end;

var
    f: TfrmContoso;

begin
  try
        f := TScreenHelperCore.FindForm<TfrmContoso>;
        if f = nil then
            f := TfrmContoso.Create(nil);

        f.ShowModal;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.
function FindForm<T: TFormClass>: T;
function FindForm<T: TForm>: T;
{$APPTYPE CONSOLE}
uses
  Vcl.Forms;

type
  TScreenHelper = class helper for TScreen
  public
    function FindForm<T: TForm>: T;
  end;

function TScreenHelper.FindForm<T>: T;
var
  f: TForm;
  i: Integer;
begin
  for i := 0 to Screen.FormCount - 1 do
  begin
    f := Screen.Forms[i];
    if (f is T) then
    begin
      Result := T(f);
      Exit;
    end;
  end;
  Result := nil;
end;

type
  TMyForm = class(TForm)
  end;

var
  Form: TMyForm;

begin
  Form := Screen.FindForm<TMyForm>;
end.