134 votes

Identificateur d’objet unique .NET

Est-il possible d'obtenir un identifiant unique d'une instance?

GetHashCode() est le même pour les deux références pointant vers la même instance. Cependant, deux cas peuvent (assez facilement) obtenir le même code de hachage:

Hashtable hashCodesSeen = new Hashtable();
LinkedList<object> l = new LinkedList<object>();
int n = 0;
while (true)
{
    object o = new object();
    // Remember objects so that they don't get collected.
    // This does not make any difference though :(
    l.AddFirst(o);
    int hashCode = o.GetHashCode();
    n++;
    if (hashCodesSeen.ContainsKey(hashCode))
    {
        // Same hashCode seen twice for DIFFERENT objects (n is as low as 5322).
        Console.WriteLine("Hashcode seen twice: " + n + " (" + hashCode + ")");
        break;
    }
    hashCodesSeen.Add(hashCode, null);
}

Je suis en train d'écrire un débogage addin, et j'ai besoin d'obtenir une sorte de ID pour une référence qui est unique au cours de l'exécution du programme.

J'ai déjà réussi à obtenir l'ADRESSE interne de l'instance, ce qui est unique jusqu'à ce que le garbage collector (GC) compacte le tas (= déplace les objets = changements d'adresses).

Un Débordement de pile question de l'implémentation par Défaut de l'Objet.GetHashCode() pourrait être liée.

[Edit] j'aurais du le dire plus clairement que les objets ne sont pas sous mon contrôle que je suis l'accès aux objets dans un programme en cours de débogage à l'aide de l'API de débogueur. Si j'étais en possession des objets, en ajoutant mes propres identifiants uniques serait trivial.

Je voulais l'ID unique pour la construction d'une table de hachage ID -> objet, pour être en mesure de recherche déjà vu des objets. Pour l'instant je l'ai résolu comme ceci:

Build a hashtable: 'hashCode' -> (list of objects with hash code == 'hashCode')
Find if object seen(o) {
    candidates = hashtable[o.GetHashCode()] // Objects with the same hashCode.
    If no candidates, the object is new
    If some candidates, compare their addresses to o.Address
        If no address is equal (the hash code was just a coincidence) -> o is new
        If some address equal, o already seen
}

76voto

Jon Points 194296

.NET 4 et plus tard seulement

Bonne nouvelle, tout le monde!

L'outil parfait pour ce travail est construit en .NET 4 et il s'appelle ConditionalWeakTable<TKey, TValue>. Cette classe:

  • peut être utilisé pour associer des données arbitraires avec la gestion des instances de l'objet comme un dictionnaire (même si c' est pas un dictionnaire)
  • ne dépend pas des adresses de mémoire, donc, est à l'abri de la GC en compactant le tas
  • ne pas garder les objets en vie juste parce qu'ils ont été inscrits en tant que clés de la table, de sorte qu'il peut être utilisé sans faire de chaque objet dans votre processus de live forever
  • utilise la référence à l'égalité pour déterminer l'identité de l'objet; par ailleurs, la classe, les auteurs ne peuvent pas modifier ce comportement, donc il peut être utilisé de manière cohérente sur les objets de tout type
  • peut être rempli à la volée, donc ne nécessite pas que vous injecter du code à l'intérieur de l'objet constructeurs

47voto

Jon Skeet Points 692016

La référence est l'identifiant unique de l'objet. Je ne sais pas de toute façon de convertir ce en quoi que ce soit comme une chaîne de caractères etc. La valeur de la référence va changer au cours de la compaction du sol (comme vous l'avez vu), mais à chaque valeur précédente sera changé à la valeur de B, donc autant que coffre-fort à code, il est encore un ID unique.

Si les objets impliqués sont sous votre contrôle, vous pouvez créer une cartographie à l'aide de références faibles (pour éviter de prévention de la collecte des ordures) à partir d'une référence à un ID de votre choix (GUID, entier, peu importe). Que serait ajouter un certain montant de frais généraux et de la complexité, cependant.

47voto

Simon Svensson Points 11667

Extrait de la ObjectIDGenerator classe? Ce n'est ce que tu essaies de faire, et ce que Marc Gravel décrit.

Le ObjectIDGenerator garde la trace déjà identifié des objets. Lorsque vous demandez de l'IDENTIFIANT de l'objet, la ObjectIDGenerator sait si le retour de l'IDENTIFIANT existant, ou de générer et mémoriser un nouvel ID.

Les Id sont uniques pour la vie de la ObjectIDGenerator instance. Généralement, un ObjectIDGenerator la vie dure aussi longtemps que le Formateur qui l'a créé. Id d'objet n'ont de sens qu'au sein d'une sérialisé flux, et sont utilisées pour le suivi des objets qui ont des références à d'autres personnes au sein de l'objet sérialisé graphique.

À l'aide d'une table de hachage, la ObjectIDGenerator conserve dont le numéro est attribué à l'objet. Les références de l'objet, qui identifient de façon unique chaque objet, sont des adresses dans le runtime déchets collectés sur le tas. Objet de référence les valeurs peuvent changer au cours de la sérialisation, mais la table est mise à jour automatiquement de façon que l'information est correcte.

Id d'objet sont 64 bits. L'Allocation commence à partir de l'un, de sorte que le zéro n'est jamais un ID d'objet valide. Un formateur peut choisir une valeur différente de zéro pour représenter un objet de référence dont la valeur est une référence null (Nothing en Visual Basic).

40voto

Anton Gogolev Points 59794

``peut aider (MSDN).

7voto

majkinetor Points 2375

Vous pouvez développer votre propre truc en une seconde. Par exemple :

Vous pouvez choisir ce que vous aimerez avoir comme identifiant unique sur votre propre, par exemple, System.Guid.NewGuid () ou simplement entier pour un accès plus rapide.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X