【问题标题】:which way is better to call this id generation method?哪种方式更好地调用此 id 生成方法?
【发布时间】:2011-04-15 15:43:56
【问题描述】:
private static Int64 NextInt64(Random rnd) 
{     
    var buffer = new byte[sizeof(Int64)];     
    rnd.NextBytes(buffer);     
    return BitConverter.ToInt64(buffer, 0); 
} 

以上方法来自这个帖子:Generate random values in C#

它将用于抽象事件类中以生成唯一的 eventId。该类将经常使用,因为我们需要发送大量事件。当我在事件类构造函数中调用上述方法时,从性能和唯一值的角度来看,哪个选项更好:

  1. new创建一个Random对象,每次都传递给上面的方法;
  2. 一开始就创建一个静态Random 对象,并在需要时使用它重复调用上述方法。

【问题讨论】:

  • 为什么不用Guids 然后Guid.NewGuid()? (评论,因为它不回答您的问题 - 它更多的是关于此代码对随机值的有效性)
  • 这是一个有效的评论 - 使用随机生成 唯一 数字是一个糟糕的决定。
  • 我不能再强调使用随机数作为“唯一密钥”的愚蠢行为。使用 64 位随机数,在大约 6.1 亿个项目后有 1% 的机会生成重复项。连续两次生成相同的数字是可能的。我强烈建议您使用其他方法来生成唯一密钥。

标签: c# .net


【解决方案1】:

创建一个 Random 实例并多次使用它肯定会更好。这样,您将获得更好的“随机性”。

如果您查看 microsoft 的文档 here,您会看到两个 Random 实例产生完全相同的数字。

另一种获得“更好”随机数的方法是提供种子。有些将当前时间作为 int 传递,以获得非常独特的种子。

【讨论】:

  • 无参数构造函数将当前时间(来自Environment.TickCount)作为种子传递。使用其他构造函数的最常见原因是,如果您想确保每次生成相同的随机数序列,通常用于测试目的。
  • 一个很好的现实世界示例是网络视频游戏 - 在多台客户端计算机上执行模拟的情况下,您可能希望确保每台客户端计算机在相同的情况下生成相同的随机数订购..
【解决方案2】:
  • 无论如何,您都需要选项 2),否则您的随机数将是相同的。见this
  • 你可以把这个方法变成一个扩展,

像这样:

 public static class Helpers
 {
   public static Int64 NextInt64(this Random rnd) { ... }
 }

但是……

它将用于抽象事件类中以生成唯一的 eventId。

不,这不会生成唯一 ID。为碰撞做好准备。

使用简单的计数器 (nextId) 或 GUId

【讨论】:

    【解决方案3】:

    System Guid 结构正是为此目的。与其尝试传递看似随机的对象,不如传递一个 guid 结构作为参数。

    private static Guid  NextIntGuid() 
    {
      return Guid.NewGuid();
    }
    

    顾名思义,它已经用于表示一个全球唯一的标识符。此外,如果您坚持使用随机数,请在 System.Security.Cryptography 命名空间内使用 RandomNumberGenerator。如果足够大,您的随机数将几乎是唯一的:

    byte[] random = new Byte[128];
    
    //RNGCryptoServiceProvider is an implementation of a random number generator.
    RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
    rng.GetBytes(random); // The array is now filled with cryptographically strong random bytes.
    

    【讨论】:

    • 退出一个繁重的Id生成函数,并返回到Randomness以防止冲突。
    【解决方案4】:

    1 会导致随机性问题,除非您每次都给它一个唯一的种子。更不用说对垃圾收集器施加额外的压力了。

    2 是一个更好的选择 - Random 类设计来生成一系列随机数,而不仅仅是一个。因此,虽然最好有一个 Random 实例,但不一定需要通过静态属性访问它,它可以通过多种方式公开。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-02
      • 1970-01-01
      • 2015-10-13
      • 2016-05-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多