Delphi:泛型和'is' - 运算符问题 [英] Delphi: generics and 'is'-operator problem

查看:327
本文介绍了Delphi:泛型和'is' - 运算符问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

根据之前的帖子,我撰写了下面的代码。请原谅这篇文章的冗长。我相信所有参与方都有更好的代码可以测试和评论。

Based on an earlier post, I've written the following code. Please excuse the verbosity of this post. I believe it's better for all parties to have the full code available to test and comment on.

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.


$ b TStr 在现实世界中会使用 Low,High:integer code>参数。如果TObject(Element)是TInt那么否则如果TObject(Element)是TStr,则有一个E2089无效类型转换 code>运行Delphi 2009.有人知道为什么会这样吗?

Note that the constructors of TInt and TStr in the real world would utilize the Low, High: integer and Length: integer parameters as well. I'm having an "E2089 Invalid typecast" at if TObject(Element) is TInt then and else if TObject(Element) is TStr then running Delphi 2009. Do anyone know why this happens?

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

Please note that TInt and TStr are just two of possibly 10-20 other types; otherwise overloading is the tool for the job. :)

推荐答案

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

Rethink your design. You may just use overloading instead of a generic type parameter, like this:

procedure Add (SomeString : TString); overload;
procedure Add (SomeInt : TInt); overload;

或者如果你想使用Gamecat建议的多态性,只是传递基本类型作为参数,在该参数上使用

Or if you want to use polymorphism do what Gamecat suggested and just pass the base type as the parameter, using is on that parameter:

procedure Add (Element : TDataType);        

像Rob在你的上一个问题的评论中指出的:如果你只允许两个类型并且具有基于实际类型的条件。所以仿制药在这里可能是错误的工具。

Like Rob pointed out in a comment to your previous question: it's not really generic if you allow only two types and have conditionals based on the actual type. So generics might be the wrong tool here.

希望有帮助。

这篇关于Delphi:泛型和'is' - 运算符问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆