Generating temporary unique (int) ID values for objects

Generating temporary unique (int) ID values for objects

Old forum URL: forums.lhotka.net/forums/t/2906.aspx


Wayne2K posted on Saturday, May 19, 2007

In one of Rockford's articles he shows some code to generate a unique integer by using a static member variable. Here is the C# example:

Public Class SomeChild

{

  private static int _lastId;

 

  private SomeChild()

  {

    // require use of factory methods

    _id = _lastId – 1;

    _lastId = _id;

  }

}


Won't this cause problems if two different threads are creating objects of the same class?

What do you think about the code below as an alternative? It produces seemingly random negative numbers, but there IS a 1 in 2 billion chance that there can be a collision.

int id = - Math.Abs(Guid.NewGuid().GetHashCode());
Debug.Print("New Id: " + id.ToString() );

Generating a Guid and hashing it is also a lot more work than just decrementing a static int. Another idea I had was to just use Interlocked.Decrement all the time (probably not a good idea).

Yet another idea was to get the pointer to the object and use that...I'm not really sure that I can trust an unmanaged pointer to remain the same throughout an object's lifetime though...

Brian Criswell replied on Saturday, May 19, 2007

Do a search of the forums.  There are several examples of a thread safe version of this.

Wayne2K replied on Monday, May 21, 2007

I found the other threads, thanks.

I ended up using Interlocked.Decrement because I saw that Microsoft uses the Interlocked class in the constructor for System.Data.DataRow, so there must not be a huge performance penalty for doing it.

Thanks!

RockfordLhotka replied on Tuesday, May 22, 2007

Since this is at least the second time this has come up, I've now updated the article on my web site to use Interlocked. That is a more correct solution.

skagen00 replied on Wednesday, May 23, 2007

This thread had another interesting approach...

http://forums.lhotka.net/forums/post/13401.aspx

The post:

 This has been an interesting thread to read. We took the compromise route in our office. None of our transactional objects (customer orders, purchase orders, etc.) know their primary key when they are new.

We have two private fields in these objects to handle the identity. One is the primary key and the other is a GUID. DataPortal_Create instanatiates the guid variable. DataPortal_Fetch instantiates the primary key variable.

Our GetIdValue overrides look like this for these objects:
Public Overrides Sub GetIdValue() As Object
    Return IIf(Me.IsNew, mFakeID, mPrimaryKey)
End Sub

The GUID doesn't go in the database, so the performance people on our team are satisfied. It really just gets used for comparison purposes. We don't explicitly use GetIdValue in any of our business or UI code.

What I liked about this was a case where one has polymorphic behavior through an inheritance chain. Let's say you have IContactMethod with Emails, Phones, Websites, etc. If you have a polymorphic collection you can't just have each class generate their own negative numbers through a static variable on the concrete classes - it's possible you'll have collisions. The use of Guids here (not for persistance but for uniqueness of new objects) seems to be a good solution. Not to mention, this behavior can  happen at the highest level of business objects (right under BusinessBase that most of our business objects descend from, rather than in each concrete class).

If there are drawbacks I'm missing w/ regards to this I certainly would be interested (as we're taking this approach).

 

Brian Criswell replied on Wednesday, May 23, 2007

Another thing to think of is that you do not have to have a separate set of negative numbers per type of object.  One set of negative numbers will work fine across all object types.  Another choice you can make is to just give every object a Guid that has nothing to do with the real id values in the object.  In the case of giving all objects the same set of numbers to work from, you can have a separate class that all classes have access to, and this separate object is in charge of decrementing ids through static methods.  There is nothing wrong with the method you are looking at using, but it may be more complicated than you need.

Copyright (c) Marimer LLC