English 中文(简体)
Delphi: generics and is -operator problem
原标题:

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.

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?

Edit: 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;

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);        

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.

Hope that helps.

问题回答

The problem is not with the generics. You add a TDataType to a list that expects TInt or 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;

Solves the problem.

But why not use:

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;




相关问题
determining the character set to use

my delphi 2009 app has a basic translation system that uses GNUGetText. i had used some win API calls to prepare the fonts. i thought it was working correctly until recently when someone from Malta ...

Help with strange Delphi 5 IDE problems

Ok, I m going nuts here. For the last (almost) four years, I ve been putting up with some extremely bad behavior from my Delphi 5 IDE. Problems include: Seemingly random errors in coride50.bpl ...

How to write a Remote DataModule to run on a linux server?

i would like to know if there are any solution to do this. Does anyone? The big picture: I want to access data over the web, using my delphi thin clients. But i´would like to keep my server/service ...

How convert string to integer in Oxygene

In Delphi, there is a function StrToInt() that converts a string to an integer value; there is also IntToStr(), which does the reverse. These functions doesn t appear to be part of Oxygene, and I can ...

Quick padding of a string in Delphi

I was trying to speed up a certain routine in an application, and my profiler, AQTime, identified one method in particular as a bottleneck. The method has been with us for years, and is part of a "...

热门标签