备用UniqueId生成技术

时间:2009-02-24 16:34:46

标签: c# .net algorithm

在应用程序中,当创建特殊类型的对象时,我需要为每个对象生成唯一ID。这些对象是在工厂中创建的,很有可能在“批量”操作中创建。我意识到框架中的“随机”毕竟不是那么“随机”,所以我尝试将时间戳添加如下:

private string GenerateUniqueId()
{
    Random randomValue = new Random();
    return DateTime.Now.Ticks.ToString() + randomValue.Next().ToString();
}

不幸的是,即使这样也行不通。对于快速连续创建的对象,我生成相同的唯一ID: - (

目前,我正在以粗暴的方式实施如下:

private string GenerateUniqueId()
{
    Random randomValue = new Random();
    int value = randomValue.Next();
    Debug.WriteLine(value.ToString());
    Thread.Sleep(100);
    return DateTime.Now.Ticks.ToString() + value.ToString();
}

由于这不是一个非常大的应用程序,我认为简单快速的技术就足够了,而不是实现精心设计的算法。

请建议。

5 个答案:

答案 0 :(得分:11)

你可能正在寻找GUID

private string GenerateUniqueId()
{
    return Guid.NewGuid().ToString("N");
}

如果您想要更小,更易于管理的ID,那么您可以使用以下内容:

private string GenerateUniqueId()
{
    using (var rng = new RNGCryptoServiceProvider())
    {
        // change the size of the array depending on your requirements
        var rndBytes = new byte[8];
        rng.GetBytes(rndBytes);
        return BitConverter.ToString(rndBytes).Replace("-", "");
    }
}

注意:与GUID的128位相比,这只会给你一个64位的数字,所以碰撞的可能性会更大。可能不是现实世界中的问题。如果这是一个问题,那么您可以增加byte数组的大小以生成更大的ID。

答案 1 :(得分:1)

假设您不想要GUID,First选项将是静态字段,并且是互锁的:

private static long lastId = 0
private static long GetNextId() {
  return Interlocked.Increment(ref lastId);
}

如果你想要基于时间刻度的东西,记住最后一个值,如果同样手动增加和保存;否则只保存:

private static long lastTick = 0;
private static object idGenLock = new Object();
private static long GetNextId() {
  lock (idGenLock) {
    long tick = DateTime.UtcNow.Ticks;
    if (lastTick == tick) {
      tick = lastTick+1;
    }
    lastTick = tick;
    return tick;
  }
}

(这些方法都不适用于多个流程。)

答案 2 :(得分:1)

在您的评论Codex中,您说使用唯一ID作为文件名。生成加密安全文件名的特定功能,Path.GetRandomFileName()

由于它具有加密安全性,即使在批处理操作中也是如此。格式有点可怕,虽然它们针对文件名进行了优化,但它也适用于其他引用。

答案 3 :(得分:0)

为什么您的工厂(可能是单线程)不能生成顺序唯一整数?如果你期望Random()工作,为什么不Guid()(或其他任何东西)?

答案 4 :(得分:0)

如果您打算使用自己的UUID发生器进行编码,请确保为发生器加盐。

我建议您查看open source package ossp-uuid,它是用于生成通用唯一标识符的ISO-C API和CLI。