Delphi通用模板类用法编译错误

Delphi通用模板类用法编译错误,delphi,generics,compiler-errors,Delphi,Generics,Compiler Errors,我是Delphi泛型类的新手。我不知道如何在实现代码中使用泛型类。 代码如下: Type TDataElement = class(TObject) protected Procedure SetName(sNewValue:String); virtual; private m_sName:String; published property sName:String read m_sName write SetName; end; Type TDataA

我是Delphi泛型类的新手。我不知道如何在实现代码中使用泛型类。 代码如下:

Type TDataElement = class(TObject)
  protected
    Procedure SetName(sNewValue:String); virtual;
  private
    m_sName:String;
  published
    property sName:String read m_sName write SetName;
end;

Type TDataArray<T : TDataElement> = class(TObject)
  public

    function Find(dtElement:T):integer; 
    Procedure Add(dtElement:T);
  private
    m_vContainer : array of T;
  protected
    Function GetData(Index:integer):T; virtual;
    Procedure SetData(Index:integer; NewValue:T); virtual;
  public
    property vData[Index: Integer]: T read GetData write SetData;
end;

implementation

function TDataArray<T>.Find(dtElement:T):integer;
var i:integer;
begin
  Result:=-1;
  for i := 0 to high(m_vContainer) do
    if (m_vContainer[i] <> NIL)and(m_vContainer[i] = dtElement) then
    begin
      Result:=i;
      exit;
    end;
end;    
.....
类型TDataElement=class(TObject)
受保护的
过程集合名(sNewValue:String);事实上的
私有的
m_sName:字符串;
出版
属性sName:String read m_sName write SetName;
结束;
类型TDataArray=class(TObject)
公众的
函数Find(dtElement:T):整数;
程序添加(DTT元素:T);
私有的
m_vContainer:T的数组;
受保护的
函数GetData(索引:整数):T;事实上的
过程SetData(索引:整数;新值:T);事实上的
公众的
属性vData[索引:整数]:T读取GetData写入SetData;
结束;
实施
函数TDataArray.Find(dtElement:T):整数;
varⅠ:整数;
开始
结果:=-1;
对于i:=0到高(m_vContainer)do
如果(m_vContainer[i]NIL)和(m_vContainer[i]=dtElement),那么
开始
结果:=i;
出口
结束;
结束;
.....
当我尝试创建泛型类的实例时,如以下代码所示: 方法1)

varz:TDataArray;
z:=TDataArray.Create();
我得到以下错误:

E2010不兼容类型:“TDataElement”和“TDataElement类”

如果我使用第二种方法,我会得到另一个奇怪的错误: 方法2) 类型TDataElementClass=TDataElement的类

var  z:TDataArray<TDataElementClass>;
varz:TDataArray;
F2084内部错误:I8230

我做错了什么

在一个文件中完整的源代码

  System.SysUtils,Classes,
  dtArray_unit in 'D:\VisionBot\Software\VisionBot\GUI\Units\dtArray_unit.pas';


Type TDataElement = class(TObject)
  protected
    Procedure SetName(sNewValue:String); virtual;
  private
    m_sName:String;
  published
    property sName:String read m_sName write SetName;
end;

Type TDataArray<T : TDataElement> = class(TObject)
  public

    function Find(dtElement:T):integer; overload;

    Procedure Add(dtElement:T);
  private

    m_vContainer : array of T;
  protected
    Function GetData(Index:integer):T; virtual;
    Procedure SetData(Index:integer; NewValue:T); virtual;
  public
    property vData[Index: Integer]: T read GetData write SetData;
end;

type
  TDerivedDataElement = class(TDataElement)
  end;

var
  z2: TDataArray<TDerivedDataElement>;


//------------------------------------------------------------------------------
Procedure TDataElement.SetName(sNewValue:String);
begin
  self.m_sName:=sNewValue;
end;
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
function TDataArray<T>.Find(dtElement:T):integer;
var i:integer;
begin
  Result:=-1;
  for i := 0 to high(m_vContainer) do
    if (m_vContainer[i] <> NIL)and(m_vContainer[i] = dtElement) then
    begin
      Result:=i;
      exit;
    end;
end;
//------------------------------------------------------------------------------
Function TDataArray<T>.GetData(Index:integer):T;
begin
  Result:=NIL;
  if Index < 0 then exit else
  if Index > high(Index) then exit else
  Result:=self.m_vContainer[Index];
end;
//------------------------------------------------------------------------------
Procedure TDataArray<T>.Add(dtElement:T);
begin
  SetLength(self.m_vContainer,Length(m_vContainer)+1);
  m_vContainer[High(m_vContainer)]:=T;
end;
//------------------------------------------------------------------------------
Procedure TDataArray<T>.SetData(Index:integer; NewValue:T);
begin
  if Index < 0 then exit else
  if Index > high(Index) then exit else
  self.m_vContainer[Index]:=T;

end;
//------------------------------------------------------------------------------


begin
  try

    z2:= TDataArray<TDerivedDataElement>.Create();

    readln;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.
System.SysUtils、类、,
“D:\VisionBot\Software\VisionBot\GUI\Units\dtArray\u unit.pas”中的dtArray\u单元;
类型TDataElement=class(TObject)
受保护的
过程集合名(sNewValue:String);事实上的
私有的
m_sName:字符串;
出版
属性sName:String read m_sName write SetName;
结束;
类型TDataArray=class(TObject)
公众的
函数Find(dtElement:T):整数;超载;
程序添加(DTT元素:T);
私有的
m_vContainer:T的数组;
受保护的
函数GetData(索引:整数):T;事实上的
过程SetData(索引:整数;新值:T);事实上的
公众的
属性vData[索引:整数]:T读取GetData写入SetData;
结束;
类型
TDerivedDataElement=类(TDataElement)
结束;
变量
z2:TDataArray;
//------------------------------------------------------------------------------
过程TDataElement.SetName(sNewValue:String);
开始
self.m_sName:=sNewValue;
结束;
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
函数TDataArray.Find(dtElement:T):整数;
varⅠ:整数;
开始
结果:=-1;
对于i:=0到高(m_vContainer)do
如果(m_vContainer[i]NIL)和(m_vContainer[i]=dtElement),那么
开始
结果:=i;
出口
结束;
结束;
//------------------------------------------------------------------------------
函数TDataArray.GetData(索引:整数):T;
开始
结果:=无;
如果索引<0,则退出else
如果索引>高(索引),则退出else
结果:=self.m_vContainer[索引];
结束;
//------------------------------------------------------------------------------
过程TDataArray.Add(dtElement:T);
开始
设置长度(self.m_vContainer,长度(m_vContainer)+1);
m_vContainer[高(m_vContainer)]:=T;
结束;
//------------------------------------------------------------------------------
过程TDataArray.SetData(索引:整数;新值:T);
开始
如果索引<0,则退出else
如果索引>高(索引),则退出else
self.m_vContainer[Index]:=T;
结束;
//------------------------------------------------------------------------------
开始
尝试
z2:=TDataArray.Create();
readln;
除了
关于E:Exception-do
Writeln(E.ClassName,“:”,E.Message);
结束;
结束。
或者这个:

type
  TDerivedDataElement = class(TDataElement)
  end;

var  
  z: TDataArray<TDerivedDataElement>;
现在,
TDataElementClass
是一个

  • TDataElement
    类型的变量可以保存
    TDataElement
    类型的实例,或者从
    TDataElement
    派生的任何类的实例
  • TDataElement类
    类型的变量可以保存类型,该类型必须是
    TDataElement
    ,或从
    TDataElement
    派生的任何类
您在问题中声称使用
TDataArray
会导致编译器错误,但事实并非如此。考虑这个编译程序:

type
  TDataElement = class
  end;

type
  TDataArray<T: TDataElement> = class
  public
    function Find(dtElement: T): Integer;
  private
    m_vContainer: array of T;
  end;

function TDataArray<T>.Find(dtElement: T): Integer;
begin
  for Result := 0 to high(m_vContainer) do
    if (m_vContainer[Result] <> nil) and (m_vContainer[Result] = dtElement) then
      exit;
  Result := -1;
end;

var
  arr: TDataArray<TDataElement>;

begin
  arr := TDataArray<TDataElement>.Create;
end.
这会失败,因为
T
是一种类型而不是实例。我想你的意思是:

m_vContainer[High(m_vContainer)]:=dtElement;
或者这个:

type
  TDerivedDataElement = class(TDataElement)
  end;

var  
  z: TDataArray<TDerivedDataElement>;
现在,
TDataElementClass
是一个

  • TDataElement
    类型的变量可以保存
    TDataElement
    类型的实例,或者从
    TDataElement
    派生的任何类的实例
  • TDataElement类
    类型的变量可以保存类型,该类型必须是
    TDataElement
    ,或从
    TDataElement
    派生的任何类
您在问题中声称使用
TDataArray
会导致编译器错误,但事实并非如此。考虑这个编译程序:

type
  TDataElement = class
  end;

type
  TDataArray<T: TDataElement> = class
  public
    function Find(dtElement: T): Integer;
  private
    m_vContainer: array of T;
  end;

function TDataArray<T>.Find(dtElement: T): Integer;
begin
  for Result := 0 to high(m_vContainer) do
    if (m_vContainer[Result] <> nil) and (m_vContainer[Result] = dtElement) then
      exit;
  Result := -1;
end;

var
  arr: TDataArray<TDataElement>;

begin
  arr := TDataArray<TDataElement>.Create;
end.
这会失败,因为
T
是一种类型而不是实例。我想你的意思是:

m_vContainer[High(m_vContainer)]:=dtElement;

看起来你把元类和类混在一起了。如何声明z
T:TDataElement
意味着可以用
TDataElement
类或任何后代类替换
T
,但不能用
TDataElement
元类(
TDataElement的class
)替换。我完全不知道元类和类之间的区别。我做了一个小编辑。即使我这样做:var z:TDataArray;z:=TDataArray.Create();我仍然得到错误(第一个方法)注意,内部错误始终是编译器中的错误。那意味着你不是在做什么
Procedure TDataArray<T>.Add(dtElement:T);
begin
  SetLength(self.m_vContainer,Length(m_vContainer)+1);
  m_vContainer[High(m_vContainer)]:=T;
end;
m_vContainer[High(m_vContainer)]:=T;
m_vContainer[High(m_vContainer)]:=dtElement;