在运行时唯一标识对象的选项?
Posted
技术标签:
【中文标题】在运行时唯一标识对象的选项?【英文标题】:Options for uniquely identifying objects at runtime? 【发布时间】:2011-01-31 17:54:59 【问题描述】:我需要在运行时为对象附加一个唯一标识符。该标识符在应用程序期间必须是唯一的。我计划在我的对象模型的基类中有一个私有成员变量来做到这一点。该变量将在对象初始化时设置,并且该值将在对象的生命周期内保持不变。在应用程序期间,没有其他对象可以具有相同的标识符。
当然,我可以使用System.Guid,但是每个对象需要 128 位的存储空间,我希望消耗更少的资源。我尝试使用 Int32 并使用 System.Environment.TickCount 属性对其进行初始化,但我没有获得足够的分辨率,并且某些对象最终分配了相同的值。
TickCounter 的文档说,TickCount 属性将在 ~29 后回滚到负数,然后再过 29 天回零。我很乐意用更高的分辨率换取更短的滚动时间。
我还有其他不知道的选择吗?
【问题讨论】:
你害怕使用 GUID 会过度消耗哪些资源?这句话听起来有点像过早的优化。我将从使用 GUID 的解决方案开始,并且只有在遇到具体的性能瓶颈时才重新考虑它。 我想太多了。谢谢大家让我走上正轨。 【参考方案1】:我建议使用整数值,并在赋值时自动递增。你可以使用Interlocked.Increment 使这个操作线程安全。
很可能,一个 32 位整数足以完成这项任务。我会推荐类似的东西:
private static newObjectId = int.MinValue;
private static int GetNextId()
return Interlocked.Increment(ref newObjectId);
然后,您可以在基类中使用它来分配新的唯一标识符。
【讨论】:
好一个。您可以将其放在需要 ID 的类中,并在构造函数中执行分配。【参考方案2】:要为对象生成唯一 ID,您可以使用我们方便地为您提供的恰当命名的 ObjectIDGenerator:
http://msdn.microsoft.com/en-us/library/system.runtime.serialization.objectidgenerator.aspx
请注意,正如注释所指出的,对象 id 生成器保持对该对象的引用处于活动状态,因此它仅适用于您知道无论如何将在应用程序生命周期内存活的对象。如果你打算在更多的临时对象上使用这个东西,那么这不是一个好的解决方案。
如果需要,您可以构建自己的对象 ID 生成器来保留弱引用;不会那么难的。
【讨论】:
有趣。该文档说 ObjectIDGenerator 用于在创建它的 Formatter 的生命周期内进行序列化,它通过维护 ID 和对象地址之间的关系来工作。从描述中不清楚 ObjectIDGenerator 对对象的引用是否会阻止对象的垃圾收集。你知道这是否使用了弱引用,或者在程序的整个生命周期中使用它是否可能是内存泄漏的来源? @Jeffrey:很好。是的,id 生成器确实保留了对象的引用。内部只是一个简单的哈希表。 我今天学到了一些东西......这就是我喜欢 *** 的原因。【参考方案3】:您是否需要标识符在所有对象中或仅在特定类型中都是唯一的?
你有几个选择:
-
如果您没有覆盖
Object.GetHashCode()
,这将为您提供一个漂亮(但不是100%)可靠的标识符。但是请注意,(根据文档),这并不能保证是唯一的。不过,您遇到重复的机会非常低。
如果您是(或需要 100%),最简单的解决方案是在您的班级中使用 private static long lastObjectId
。在基本构造函数中,使用 Interlocked.Increment(ref lasObjectId)
作为当前对象的值。
如果您需要标识符在对象之间是唯一的,您可以执行类似于 2. 的操作,但您必须使用中心类来管理这些 ID。
【讨论】:
【参考方案4】:如果唯一性只是在应用程序的生命周期内,你不能使用一个 32 位整数,初始化为零,然后随着每个对象分配简单地递增吗?
无需担心 TickCount 或类似的事情。数字“2”在数字中是唯一的;如果您要测试的只是相等性,那么它与“1”和“3”的区别与“1,203,718”的区别一样。
【讨论】:
你最后一句话让我想起了圣手榴弹的说明以上是关于在运行时唯一标识对象的选项?的主要内容,如果未能解决你的问题,请参考以下文章