Guid
如果您对 ID 类型没有任何限制,则可以使用 GUID:
Dim id As Guid = Guid.NewGuid()
您甚至可以将其保留为字符串:
Dim id As String = Guid.NewGuid().ToString("N")
这应该被认为在不同的机器上是唯一的(以满足您的要求,它必须是适合用作数据库中的主键)。也可以看看这个帖子 https://stackoverflow.com/questions/10951828/is-it-safe-to-assume-boostuuid-wont-return-a-duplicate/10951940#10951940.
时间戳
更糟糕的情况是,如果您没有如此严格的要求(整个网络的唯一性),您可以使用时间戳。当然,在这种情况下,你还要考虑更多的问题:
- 法定时间:时间每年往返两次。
- 区域:如果用户在伦敦输入数据然后搬到纽约怎么办?
- 并发性:您必须假设没有其他人向您的数据库添加记录(如果他们使用不同的技术,您可能会发生冲突)。此外,如果执行是并发的(程序的多个实例一起运行),则不能应用此功能。
- 计时器粒度:系统日期的粒度较粗:如果您在短时间内构造了许多对象,则可能会出现重复的 ID。解决方法在这个帖子 https://stackoverflow.com/questions/1416139/how-to-get-timestamp-of-tick-precision-in-net-c.
Counter
如果满足所有这些条件:
- 应用程序的多个实例不会并行运行。
- 您正在一台计算机(而不是网络)上工作。
- 每次应用程序启动时,数据库都是空的。
您可以使用Shared
每次构造新对象时计数器都会递增。如果系统计时器粒度不是问题(请参阅有关时间戳的段落),您可以使用系统正常运行时间 https://stackoverflow.com/questions/972105/retrieve-system-uptime-using-c-sharp作为身份证。由于粒度的限制,即使同一应用程序的多个实例同时运行,它也应该可以工作。
如果您使用Shared
您必须处理同步问题的领域。正如建议的这条评论 https://stackoverflow.com/questions/21433670/auto-generate-unique-id-within-the-constructor-in-vb-net/21433768#comment32338574_21433768你可以使用SyncLock
。作为替代方案,您可以使用Interlocked.Increment
手术。
哈希码
如果计数器的所有条件都满足,并且该计数器也满足:
- 您的应用程序是 32 位的。
- 你的对象不是
ValueType
并且它不会覆盖GetHashCode()
method.
您可以使用哈希码(通过以下方式获得)GetHashCode()
)因为(从MSDN http://msdn.microsoft.com/en-us/library/system.object.gethashcode.aspx):
换句话说,ReferenceEquals 方法返回 true 的两个对象具有相同的哈希码。
Because Object.ReferenceEquals()
回报true
仅当您比较相同的实例时,每个实例才会有唯一的哈希代码(因为在 32 位应用程序中,哈希代码是对象引用本身)。请注意,这是一个实现细节,可能会发生变化。
随机数
我知道这可能会让某些人感到震惊,但是一个好的 64 位值随机数生成器发生冲突的可能性非常低。我重复非常非常低概率(见本文 http://en.wikipedia.org/wiki/Birthday_paradox#Approximation_of_number_of_people了解更多数学细节)。只是不使用System.Random
为了这!
根据您使用的种子,您也可以在网络场景中生成随机数(不要忘记 - 需要引用 - 一个本地网络协议的早期草案提出了 32 位随机数作为地址,它已被更改,因为用户的反馈不好,但这并不意味着它不能工作)。