2011-01-31 23 views
5

Necesito adjuntar un identificador único a los objetos en tiempo de ejecución. El identificador debe ser único para la duración de la aplicación. Planeo hacer esto teniendo una variable miembro privada en la clase base de mi modelo de objetos. Esta variable se establecerá en la inicialización del objeto y el valor permanecerá constante durante la vida del objeto. Ningún otro objeto puede tener el mismo identificador para la duración de la aplicación.Opciones para identificar objetos de manera única en el tiempo de ejecución?

Puedo, por supuesto, usar un System.Guid, pero eso cuesta 128 bits de almacenamiento para cada objeto y me gustaría consumir menos recursos. Intenté usar un Int32 e inicializarlo con la propiedad System.Environment.TickCount, pero no obtuve la resolución suficiente y algunos objetos terminan teniendo el mismo valor asignado.

La documentación para el TickCounter dice que la propiedad TickCount pasará a ser negativa después de ~ 29 y luego volverá a cero en otros 29 días. Me encantaría intercambiar más resolución por una tirada más corta con el tiempo.

¿Tengo otras opciones que no conozco?

+3

¿Qué recursos temes que usar GUID consumará en exceso? Esa afirmación suena un poco como una optimización prematura. Comenzaría con una solución que usa GUID y solo la reconsidere si encuentra cuellos de botella de rendimiento concretos. –

+0

Estaba pensando en el problema. Gracias a todos por ponerme en camino. –

Respuesta

13

Recomendaría usar un valor entero y autoincrementarlo en la asignación. Puede usar Interlocked.Increment para hacer que esta operación sea segura.

Lo más probable es que un entero de 32 bits sea lo suficientemente grande para esta tarea. Recomendaría algo como:

private static newObjectId = int.MinValue; 

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

Puede usar eso en su clase base para asignar un nuevo identificador único.

+0

. Pégame. :) –

+0

Bueno. Pondría esto en la clase para la que necesita el ID, y realice la asignación en el constructor (es). – KeithS

2

Si la exclusividad es solo por la vida útil de la aplicación, ¿no puede usar un entero de 32 bits, inicializar a cero y luego simplemente aumentar con cada asignación de objeto?

No hay necesidad de preocuparse por TickCount ni nada de eso. El número "2" es único entre los números; es tan diferente de "1" y "3" como de "1,203,718" si todo lo que está probando es la igualdad.

+1

Algo acerca de tu última oración me recuerda las instrucciones para la Holy Hand Grenade –

3

¿Necesita el identificador para ser único en todos los objetos o solo dentro de un tipo específico?

usted tiene un par de opciones:

  1. Si no está sustituyendo Object.GetHashCode(), esto le dará una muy (pero no al 100%) identificador fiable . Sin embargo, tenga en cuenta que (según los documentos), esto no es garantizado para ser único. Sin embargo, tus posibilidades de acertar a un duplicado son bastante bajas.
  2. Si es (o necesita 100%), la solución más simple sería usar un private static long lastObjectId en su clase. Dentro del constructor base, use Interlocked.Increment(ref lasObjectId) como el valor para el objeto actual.
  3. Si necesita que el identificador sea único en todos los objetos, puede hacer algo similar a 2., pero deberá usar una clase central para administrar estos ID.
+0

+1 para enclavamiento –

8

Para generar los identificadores únicos para objetos que puede utilizar el bien llamado ObjectIDGenerator que convenientemente proporcionar para usted:

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

Tenga en cuenta que, como el comentario señala, el generador de identificador de objeto mantiene una referencia al objeto vivo, por lo que solo es adecuado para objetos que usted sabe que van a sobrevivir la vida de la aplicación de todos modos. Si tiene la intención de utilizar esta cosa en objetos más efímeros, entonces no es una buena solución.

Puede construir su propio generador de ID de objetos que mantiene las referencias débiles si lo desea; no sería tan difícil.

+2

Interesante. El documento dice que ObjectIDGenerator está destinado para su uso en la serialización durante el tiempo de vida del formateador que lo creó, y funciona manteniendo una relación entre los identificadores y las direcciones de los objetos. A partir de la descripción, no está claro si la referencia de ObjectIDGenerator a un objeto evitará la recolección de basura del objeto. ¿Sabes si esto utiliza referencias débiles, o si podría ser la fuente de una pérdida de memoria cuando se utiliza durante la vida de un programa? –

+1

@Jeffrey: Excelente punto. Sí, el generador de id mantiene una referencia al objeto. Es solo una simple tabla hash internamente. –

+0

Hoy aprendí algo ... por eso me gusta StackOverflow. –

Cuestiones relacionadas