为什么这段代码不能在XE3中编译

时间:2012-10-05 15:23:56

标签: delphi generics delphi-xe2 delphi-xe3

type
  TForm72 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }    
  end;

  TTestForm = class(TForm)
  public
    constructor CreateTest(AOwner: TComponent); virtual;
  end;

  TTestForm1 = class(TTestForm)    
  public
    constructor CreateTest(AOwner: TComponent); override;
  end;

  TTest<T: TTestForm, constructor> = class(TObject)
  public
    class procedure Test;
  end;

var
  Form72: TForm72;

implementation

{$R *.dfm}

procedure TForm72.FormCreate(Sender: TObject);
begin
  TTest<TTestForm1>.Test;
end;

{ TTest<T> }

class procedure TTest<T>.Test;
var
  F: T;
begin
  F := T.CreateTest(Application);
  Form72.Caption :=  F.Name;
end;

{ TTestForm }

constructor TTestForm.CreateTest(AOwner: TComponent);
begin
  inherited Create(AOwner);
end;

{ TTestForm1 }

constructor TTestForm1.CreateTest(AOwner: TComponent);
begin
  inherited;
  Caption := 'Bang';
end;

end.

此代码在XE2中编译,但失败并出现“[dcc32错误] Unit71.pas(55):E2010不兼容的类型:XE3中的'T'和'过程,无类型指针或无类型参数'”。我做错了什么,还是编译错了?

1 个答案:

答案 0 :(得分:4)

实际上,此代码突出显示了XE2中的编译器错误。在XE2中,代码在不应该编译时编译。删除constructor约束,编译失败并显示

E2568 Can't create new instance without CONSTRUCTOR constraint in type 
parameter declaration

constructor约束仅表明该类具有无参数构造函数。 documentation州:

  

构造函数约束

     

类型参数可以由零或一个实例约束   保留字“构造函数”。这意味着实际的参数类型   必须是一个定义默认构造函数的类(public   无参数构造函数),使泛型类型中的方法   可以使用参数类型构造参数类型的实例   默认构造函数,不知道有关参数类型的任何信息   本身(没有最低基本类型要求)。

constructor约束的存在或其他因素影响此代码的事实表明XE2编译器有错误。


在XE3中,代码无法正确编译。使用语法T.Create调用构造函数的唯一方法是使用constructor约束并调用无参数构造函数。这不是这种情况,因此XE3正确报告编译错误。

你需要一些演员才能进行编译。

F := T(TTestForm(T).CreateTest(Application));

这是一个well-known trick来解决Delphi泛型实现处理构造函数的一些怪癖。虽然看起来很乱,但我相信这段代码是语言设计者打算使用的。在我看来,行为的改变是由于错误修复而XE3的行为与设计相符。