2010-11-08 7 views
1

Comment puis-je commander (comparer) des objets .NET par référence? J'utiliserais ceci pour déterminer efficacement si deux collections .NET contiennent les mêmes instances (par référence, pas par valeur). Une autre façon de formuler cette question pourrait être de demander une implémentation de IComparer qui utilise la comparaison de référence plutôt que la comparaison de valeurs.Trier les objets .NET par référence, et non la valeur

Remarque en Java, j'utiliserais System.identityHashCode().

+2

"commande par" référence? Deux références peuvent seulement être "égales" ou "inégales", pas "supérieures/inférieures". –

+0

Je m'attendrais à ce que le runtime puisse me fournir un ordre arbitraire (mais fixe) sur les références. Si je pouvais trier les deux collections par ce comparateur, alors je pourrais vérifier plus efficacement si les collections contiennent exactement les mêmes instances d'objet. – pauldoo

+0

Ce n'est pas efficace, il nécessite O (nlog (n)) heure et O (n) de stockage. La recherche de doublons nécessite seulement le temps O (n) et le stockage. –

Répondre

5

Utilisez Object.ReferenceEquals().

Notez que la comparaison de reference types à l'aide de l'opérateur == fait également ce que vous voulez, à moins que l'opérateur d'égalité ne soit surchargé dans ces types.

EDIT:System.Object a GetHashCode(), qui fonctionne de la même manière que Java de hashCode(). Son comportement peut être assez similaire à identityHashCode() pour répondre à vos besoins, mais je ne comprends pas comment comparer les références ou les codes de hachage serait représentatif de la valeur réelle de vos objets.

+1

Je veux une comparaison, pas une vérification de l'égalité. – pauldoo

+0

@pauldoo: Pouvez-vous élaborer ce que vous voulez avec un exemple? –

+0

J'ai deux instances de 'ICollection '. Je souhaite savoir si les deux instances contiennent exactement le même ensemble d'objets (par égalité de référence). – pauldoo

1

Pas une réponse directe à votre question, mais une solution à votre problème réel en utilisant LINQ:

IEnumerable<Foo> items = new List<Foo>(){ new Foo(), new Foo() }; 
IEnumerable<Foo> otheritems = items; 

bool identical = items.Intersect(otheritems).ToArray().Count() == items.Count(); 

Cela fonctionne en comparant les références, à moins que la méthode Equals est remplacée dans le type Foo.

1

Vous ne pouvez pas commander littéralement des objets .NET par référence ... apparemment vous ne pouvez pas utiliser même code « dangereux » pour convertir une référence à un entier:

unsafe int ReferenceToInt(object o) 
{ 
    // Error: cannot declare a pointer to a managed type. 
    fixed (object* ptr = o) 
     return (int)ptr; 
} 

Ce ne serait pas un bonne idée de toute façon, car une collection de garbage compactage pourrait changer non seulement l'adresse de chaque objet, mais l'ordre relatif entre les objets. Même si le GC n'a pas changé d'ordre relatif, le GC peut fonctionner à tout moment, ce qui rendrait la commande par référence très dangereuse.

L'implémentation par défaut de GetHashCode() renvoie une sorte d'ID d'objet que vous pouvez utiliser à la place. Et, comme Frédéric l'a mentionné, vous pouvez utiliser Object.ReferenceEquals() pour confirmer que deux références sont identiques. Enfin, dans la plupart des cas, vous devriez simplement utiliser Dictionary, HashSet ou LINQ, comme d'autres l'ont mentionné.

Questions connexes