Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Delphi 德尔菲:泛型和';是'-操作员问题_Delphi_Generics_Casting - Fatal编程技术网

Delphi 德尔菲:泛型和';是'-操作员问题

Delphi 德尔菲:泛型和';是'-操作员问题,delphi,generics,casting,Delphi,Generics,Casting,基于前面的一个示例,我编写了以下代码。请原谅这篇文章的冗长。我认为最好让各方都有完整的代码可供测试和评论 program sandbox; {$APPTYPE CONSOLE} uses SysUtils, Generics.Collections; type TDataType = class // Stuff common to TInt and TStr end; TInt = class(TDataType) FValue: integer;

基于前面的一个示例,我编写了以下代码。请原谅这篇文章的冗长。我认为最好让各方都有完整的代码可供测试和评论

program sandbox;
{$APPTYPE CONSOLE}

uses
  SysUtils,
  Generics.Collections;

type
  TDataType = class
    // Stuff common to TInt and TStr
  end;

  TInt = class(TDataType)
    FValue:  integer;
    constructor Create(Value, Low, High: integer);
  end;

  TStr = class(TDataType)
    FValue: string;
    constructor Create(Value: string; Length: integer);
  end;

  TSomeClass = class
    FIntList: TList<TInt>;
    FStrList: TList<TStr>;
    procedure AddToList<T: TDataType>(Element: T);
    constructor Create();
    procedure Free();
  end;

constructor TInt.Create(Value, Low, High: Integer);
begin
  inherited Create();
  FValue := Value;   
end;

constructor TStr.Create(Value: string; Length: Integer);
begin
  inherited Create();
  FValue := Value;
end;

procedure TSomeClass.AddToList<T>(Element: T);
begin
  if TObject(Element) is TInt then
    FIntList.Add(Element)
  else if TObject(Element) is TStr then
    FStrList.Add(Element);
end;

constructor TSomeClass.Create();
begin
  inherited;
  FIntList := TList<TInt>.Create();
  FStrList := TList<TStr>.Create();
end;

procedure TSomeClass.Free();
var
  SomeIntItem: TInt;
  SomeStrItem: TStr;
begin
  for SomeIntItem in FIntList do begin
    SomeIntItem.Free();
  end;

  for SomeStrItem in FStrList do begin
    SomeStrItem.Free;
  end;

  FIntList.Free();
  FStrList.Free();
end;

var
  Inst: TSomeClass;

begin
  try
    { TODO -oUser -cConsole Main : Insert code here }

    Inst := TSomeClass.Create;
    Inst.AddToList(TInt.Create(100, 0, 101));
    Inst.AddToList(TStr.Create('Test', 10));
    Inst.Free;

  except
    on E:Exception do
    Writeln(E.Classname, ': ', E.Message);
  end;
end.
程序沙盒;
{$APPTYPE控制台}
使用
SysUtils,
仿制药。收藏;
类型
TDataType=class
//着色和TStr常见的材料
结束;
色调=类别(TDataType)
FValue:整数;
构造函数创建(值、低、高:整数);
结束;
TStr=类(TDataType)
FValue:string;
构造函数创建(值:字符串;长度:整数);
结束;
TSomeClass=class
FIntList:TList;
FStrList:TList;
程序添加列表(元素:T);
构造函数Create();
无程序();
结束;
构造函数着色创建(值、低、高:整数);
开始
继承Create();
FValue:=值;
结束;
构造函数TStr.Create(值:字符串;长度:整数);
开始
继承Create();
FValue:=值;
结束;
程序TSomeClass.AddToList(元素:T);
开始
如果TObject(元素)是淡色,则
FIntList.Add(元素)
否则,如果TObject(元素)是TStr,则
FStrList.Add(元素);
结束;
构造函数TSomeClass.Create();
开始
继承;
FIntList:=TList.Create();
FStrList:=TList.Create();
结束;
过程TSomeClass.Free();
变量
一些元素:色调;
部分项目:TStr;
开始
对于FIntList中的某些项目,请开始
SomeIntItem.Free();
结束;
对于FStrList中的某些项,请务必开始
自由的;
结束;
FIntList.Free();
Free();
结束;
变量
研究所:托米班;
开始
尝试
{TODO-oUser-cConsole Main:在此处插入代码}
Inst:=TSomeClass.Create;
Inst.AddToList(着色创建(100,0,101));
仪器添加列表(TStr.Create('Test',10));
仪器免费;
除了
关于E:Exception-do
Writeln(E.Classname,“:”,E.Message);
结束;
结束。
请注意,真实世界中的
TInt
TStr
的构造函数也将使用
Low、High:integer
Length:integer
参数。如果TObject(Element)是TInt,则在
处有一个“E2089无效类型转换”,否则如果TObject(Element)是TStr,则运行Delphi 2009。有人知道为什么会这样吗


编辑:请注意,
TInt
TStr
只是其他10-20种类型中的两种;否则,重载是作业的工具。:)

重新思考你的设计。您可以只使用重载而不是泛型类型参数,如下所示:

procedure Add (SomeString : TString); overload;
procedure Add (SomeInt : TInt); overload;
或者,如果您想使用多态性,请按照Gamecat的建议执行操作,并将基本类型作为参数传递,在该参数上使用
is

procedure Add (Element : TDataType);        
就像Rob在对上一个问题的评论中指出的那样:如果只允许两种类型并且有基于实际类型的条件,那么它就不是真正的泛型。因此,泛型可能是错误的工具


希望有帮助。

问题不在于泛型。将TDataType添加到需要色调或TStr的列表中:

procedure TSomeClass.AddToList<T>(Element: T);
begin
  if TObject(Element) is TInt then
    FIntList.Add(TInt(Element))
  else if TObject(Element) is TStr then
    FStrList.Add(TStr(Element));
end;

您对AddToList的声明和实现有所不同。我对泛型的了解还不够,但对于常规的pascal,这是错误的。嗨,Lieven!我想您指的是实现“procedure TSomeClass.AddToList(Element:T)”而不是签名“procedure AddToList(Element:T)”?如果是这样,对你评论的回应是RAD studio不希望实际实现受到限制。啊,我明白了。至少最明显的是,对于那些还没有进入泛型的人来说,现在已经过时了。谢谢你的澄清。只是出于好奇:在一个单独的列表中存储每种数据类型有什么意义?为什么不使用
t列表
?您真的必须单独处理每种数据类型吗?你不能提取一个公共签名并使用多态性吗?谢谢你!老实说,我甚至没有想到这一点。然而,我不确定这是我真正的代码中的方式。TInt的所有实例在逻辑上与TStr的实例分开。所以把他们分开是相当明智的。。。但很明显,关于多态性,我还有很多东西要学。在这一点上,我将后退一步,考虑其他设计方案。顺便说一句:我仍然不明白为什么类型转换是非法的。它没有编译器错误。它缺少一个类型转换;-)。但是我同意错误的工具评论。谢谢你!我意识到我应该从一开始就指出,TInt和TStr还将伴随着10多种其他类型。我不知道TypeInfo()方法,因此为此+1:)你是说我刚刚删除的那个吗?:)下面是巴里·凯利最初答案的链接,以防有人怀疑:是的,就是这个!我意识到这可能是常识,但大约四个月前我开始使用Delphi,所以从所有标准来看我都是新手。同时也感谢您的设计输入。@conciliator:即使您有10多个不同的类型,如果您想将它们放入10多个不同的列表中,泛型并不是最好的选择,重载方法更好(+1)。在任何情况下,如果您对Delphi比较陌生,我强烈建议您不要使用泛型,除非有真正令人信服的理由-至少在Delphi 2009中,我们开发人员被视为这一新功能的巨大现场测试,你永远也不知道当事情不顺利的时候,是你自己出了差错还是编译器出了问题。谢谢你,Gamecat!最后一个示例编译得很好。然而,使用第一个示例(尝试了T:TDataType、T:class和空约束),我仍然得到一个类型转换错误。你把它编译好了吗?@Gamecat:也许我一开始就不清楚?语句“如果TObject(Element)是TInt then”和“否则如果TObject(Element)是TStr then”中的类型转换失败。。。你知道为什么吗?我刚刚测试了你的代码。
TObject(Element)
cast工作正常,而
FIntList.Add(Element)
会产生一条“invalid type:T and TInt”错误消息——正如Gamecat所说。这很奇怪。我上传了一个屏幕转储:。我做错了什么?哪个德尔夫
procedure TSomeClass.AddToList(Element: TDataType);
begin
  if Element is TInt then
    FIntList.Add(TInt(Element))
  else if Element is TStr then
    FStrList.Add(TStr(Element));
end;