Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I obtain an ID that allows me to tell difference instances of a class apart?

Tags:

Imagine I have a single class, with two instances:

MyClass a = new MyClass(); MyClass b = new MyClass(); 

MyClass has a method PrintUniqueInstanceID:

void PrintUniqueInstanceID() {   Console.Write("Unique ID for the *instance* of this class: {0}",        [what goes here???]   ); } 

Ideally, the output would be something like:

Unique ID for the *instance* of this class: 23439434        // from a.PrintUniqueInstanceID Unique ID for the *instance* of this class: 89654           // from b.PrintUniqueInstanceID 

So - what would I insert in "[what goes here???]", above, which prints a unique number for every unique instance of the class?

Ideas

  1. Perhaps cast "this" to an int pointer, and use that?
  2. Use GCHandle somehow?
  3. Access a property of "this", within the method, to uniquely identify it?

(optional) Background Information For Experts

The reason I need this is that I am using AOP and PostSharp to automatically detect threading issues. I need to look up each unique instance of the class in a dictionary, in order to verify that multiple threads are not accessing the same unique instance of a class (its ok if there is one thread per class instance).

Update

As others have pointed out, I should mention that I can't touch any of the existing classes in the 30,000 line project. PrintUniqueInstanceID, above, is an aspect (see PostSharp) that is added to the top level class, is inherited by every class in the entire project, and executes on every method entry in the entire project.

Once I have verified that everything is thread safe, I'll remove the aspect to restore performance.

like image 370
Contango Avatar asked Mar 20 '12 14:03

Contango


2 Answers

Add a Guid property to your class, then in the constructor of the class assign it to NewGuid().

public class MyClass {     public Guid InstanceID {get; private set;}     // Other properties, etc.      public MyClass()     {         this.InstanceID = Guid.NewGuid();     }      void PrintUniqueInstanceID()      {            Console.Write("Unique ID for the *instance* of this class: {0}", this.InstanceID);      }  } 
like image 187
mgnoonan Avatar answered Sep 23 '22 16:09

mgnoonan


Revised answer

Based on the additional information we now have, I believe that you can solve your problem very easily using ConditionalWeakTable (which is only from .NET 4 onwards).

  • it can be used to associate arbitrary data with managed object instances
  • it does not keep objects "alive" just because they have been entered as keys into the table
  • it uses reference equality to determine object identity; moveover, class authors cannot modify this behavior (handy since you are not the author of every class on earth)
  • it can be populated on the fly

You can therefore create such a global table inside your "manager" class and associate each object with a long, a Guid or anything else you might want¹. Whenever your manager encounters an object it can get its associated id (if you have seen it before) or add it to the table and associate it with a new id created on the spot.

¹ Actually the values in the table must be of a reference type, so you cannot use e.g. long as the value type directly. However, a simple workaround is to use object instead and let the long values be boxed.

Original answer

Isn't this a basic usage example for static members?

class Foo {     private static int instanceCounter;     private readonly int instanceId;      Foo()     {         this.instanceId = ++instanceCounter;     }      public int UniqueId     {         get { return this.instanceId; }     } } 

Of course you have to pay attention to the range of identifiers so that you don't start reusing them if billions of instances are created, but that's easy to solve.

like image 34
Jon Avatar answered Sep 23 '22 16:09

Jon