Options for uniquely identifying objects at runtim

2020-02-29 01:59发布

问题:

I need to attach a unique identifier to objects at runtime. The identifier must be unique for the duration of the application. I plan to do this my having a private member variable in the base class of my object model. This variable will be set at object initialization and the value will remain constant for the life of the object. No other object can have the same identifier for the duration of the application.

I can, of course, use a System.Guid, but that costs a 128 bits of storage for each object and I would like to consume fewer resources. I tried using an Int32 and initializing it with the System.Environment.TickCount property, but I don't get enough resolution and some objects wind up having the same value assigned.

The documentation for the TickCounter says that the TickCount property will roll to negative after ~29 and then back to zero in another 29 days. I would happly trade more resolution for a shorter roll over time.

Do I have other options that I don't know about?

回答1:

I would recommend using an integer value, and auto-incrementing it on assignment. You could use Interlocked.Increment to make this operation thread safe.

Most likely, a 32bit integer will be large enough for this task. I would recommend something like:

private static newObjectId = int.MinValue;

private static int GetNextId()
{
    return Interlocked.Increment(ref newObjectId);
}

You can then use that in your base class for assigning a new, unique identifier.



回答2:

To generate unique ids for objects you could use the aptly named ObjectIDGenerator that we conveniently provide for you:

http://msdn.microsoft.com/en-us/library/system.runtime.serialization.objectidgenerator.aspx

Note that, as the comment points out, the object id generator keeps a reference to the object alive, so it is only suitable for objects that you know are going to survive the life of the application anyway. If you intend to use this thing on more ephemeral objects then it is not a good solution.

You could build your own object ID generator that kept weak references if you wanted; it wouldn't be that difficult.



回答3:

Do you need the identifier to be unique across all objects or just within a specific type?

You have a couple of options:

  1. If you aren't overriding Object.GetHashCode(), this will give you a pretty (but not 100%) reliable identifier. Note, though, that (per the docs), this is not guaranteed to be unique. Your chances of hitting a duplicate, though, are pretty low.
  2. If you are (or need 100%), the simplest solution would be to use a private static long lastObjectId in your class. Within the base constructor, use Interlocked.Increment(ref lasObjectId) as the value for the current object.
  3. If you need the identifier to be unique across objects, you can do something similar to 2., but you'll have to use a central class to manage these ID's.


回答4:

If the uniqueness is just for the life of the application, can't you use a 32-bit integer, initialized to zero, and then simply incremented with each object allocation?

There's no need to worry about TickCount or anything like that. The number "2" is unique among numbers; it's as different from "1" and "3" as it is from "1,203,718" if all you're testing for is equality.