2008-11-06 5 views
2

Je vérifie l'essai Delphi 2009, mais j'ai rencontré des problèmes avec les génériques tout de suite.Delphi 2009 problème de compilation de génériques

Le code suivant ne compile pas, et je n'ai pas la moindre idée pourquoi il me donne E2015 pour la méthode equals():

type 
    TPrimaryKey<T> = class(TObject) 
    strict private 
    fValue: T; 
    public 
    constructor Create(AValue: T); 
    function Equals(Obj: TObject): boolean; override; 
    function GetValue: T; 
    end; 

constructor TPrimaryKey<T>.Create(AValue: T); 
begin 
    inherited Create; 
    fValue := AValue; 
end; 

function TPrimaryKey<T>.Equals(Obj: TObject): boolean; 
begin 
    Result := (Obj <> nil) and (Obj is TPrimaryKey<T>) 
    and (TPrimaryKey<T>(Obj).GetValue = fValue); 
end; 

function TPrimaryKey<T>.GetValue: T; 
begin 
    Result := fValue; 
end; 

Pourquoi pense que le compilateur qui fValue et le résultat de GetValue() ne peut pas être comparé?

Répondre

6

si T est une chaîne? Et si c'est un disque TSize?

Sans contrainte T (par exemple avec < T: class>), vous ne pouvez pas être sûr que la comparaison sera significative.

Si, au contraire, que vous vouliez comparer deux valeurs de type T, vous pouvez utiliser l'unité et de l'utilisation Generics.Defaults:

TEqualityComparer<T>.Default.Equals(x, y) 

pour comparer les valeurs x et y de type T.

+0

Je ne comprends pas votre première phrase (je crois que le code ne le fait pas), mais remplacer le contrôle d'égalité dans Equals() par votre code TEqualityComparer résout mon problème, merci. Malheureusement, la documentation et les échantillons sont - encore une fois - une complète déception dans Delphi 2009 :-( – mghie

3

Vous ne pouvez pas utiliser d'opérateurs avec des génériques non typés. Voir here pour une discussion.

Il compile si vous modifiez à:

TPrimaryKey<T: class> = class(TObject) 
+0

Merci Pour le lien, ce qui suit m'a ouvert les yeux: "Les génériques sont compilés avant de se spécialiser avec le type final " Je pense qu'en termes de templates C++ c'est juste faux, et les génériques Delphi ne sont pas une solution à mon problème . – mghie

+0

Correction de faute de frappe: I _guess_ thinking ... – mghie

2

Je pense que l'affiche originale tente de créer une enveloppe d'objet autour de types simples (entier, double etc etc), ce qui limite donc T à la classe serait peut-être pas travaille pour ce qu'il veut.

+0

En effet. Mais il semble que les génériques tels que mis en œuvre dans Delphi 2009 ne sont pas ce que j'espérais qu'ils seraient. – mghie

+0

Le problème est que, contrairement à .net, dans delphi, les types simples ne sont pas des objets. – Steve

1

Le compilateur a du mal à déterminer si les deux "T" sont identiques. Mais avec un petit truc, vous pouvez le faire fonctionner:

type 
    TPrimaryKey<T> = class(TObject) 
    public 
    type 
     TCompare<T1> = reference to function(const A1, A2: TPrimaryKey<T1>): Boolean; 
    private 
    fValue: T; 
    fCompare : TCompare<T>; 
    public 
    constructor Create(AValue: T; ACompare: TCompare<T>); 
    function Equals(Obj: TPrimaryKey<T>): Boolean; reintroduce; 
    function GetValue: T; 
    function CreateNew(const AValue: T): TPrimaryKey<T>; 

    end; 

constructor TPrimaryKey<T>.Create(AValue: T; ACompare: TCompare<T>); 
begin 
    inherited Create; 
    fValue := AValue; 
    fCompare := ACompare; 
end; 

function TPrimaryKey<T>.Equals(Obj: TPrimaryKey<T>): Boolean; 
begin 
    Result := FCompare(self, Obj); 
end; 

function TPrimaryKey<T>.GetValue: T; 
begin 
    Result := fValue; 
end; 

function TPrimaryKey<T>.CreateNew(const AValue: T): TPrimaryKey<T>; 
begin 
    Result := TPrimaryKey<T>.Create(AValue, FCompare); 
end; 

instanciation avec:

var 
    p1, p2 : TPrimaryKey<Integer>; 
begin 
    p1 := TPrimaryKey<Integer>.Create(10, 
    function(const A1, A2: TPrimaryKey<Integer>): Boolean 
    begin 
     Result := (A1<>nil) and (A2<>nil) and (A1.GetValue=A2.GetValue); 
    end); 
    p2 := p1.CreateNew(10); 

    p1.Equals(p2); 
end;