C#中"静态"Random.Next的正确方法?

Sun*_*nil 27 c# random

为什么我需要创建一个Random类的实例,如果我想创建1到100之间的随机数....就像

Random rand = new Random();
rand.Next(1,100);
Run Code Online (Sandbox Code Playgroud)

Random类是否有任何静态函数来做同样的事情?喜欢...

Random.Next(1,100);
Run Code Online (Sandbox Code Playgroud)

我不想不必要地创建一个实例

Kob*_*obi 34

最佳做法是Random在整个程序中创建单个实例并使用它 - 否则结果可能不是随机的.不创建静态函数会鼓励这种行为.

你不应该担心"不必要地创建一个实例",影响最多可以忽略不计 - 这就是框架的工作方式.

  • 如果Random是静态的,那可能无法实现吗?发电机将在施工时播种,您可以在整个过程中使用它吗? (9认同)
  • @Asher:但是Random不是线程安全的,所以如果你想从多个线程中调用Random而不能工作......除此之外,如果你想为你的Random类多个种子?例如,我想使用多个线程,每次执行时会产生相同的结果,要求我使用具有相同种子的多个实例,静态则是竞赛. (6认同)
  • @Asher - 无论如何都需要内部实例,并且需要状态.我不认为它属于框架的一部分,但它可以在您的静态类上轻松实现. (2认同)
  • @Kobi也许我应该发布我自己的问题:).除了内存使用和性能之外,我觉得实例化这个类很烦人.如果您只是要使用一个,为什么不让它静止.这是关于我没有得到的静态类的东西.无论如何,我离题了 (2认同)
  • 考虑可重用性 - *你*认为你只称它一次,但有一天也许有人会将你的功能称为1000次,而你会失去随机性.如果您发现实例化类很烦人,可能C#不太适合您:) (2认同)

Pra*_*are 27

//Function to get random number
private static readonly Random random = new Random();
private static readonly object syncLock = new object();
public static int RandomNumber(int min, int max)
{
    lock(syncLock) { // synchronize
        return random.Next(min, max);
    }
}
Run Code Online (Sandbox Code Playgroud)

直接复制

  • 这非常适合避免错过使用类,如Evgeny的答案.+1也引用了代码,信用它到期:) (4认同)

EMP*_*EMP 6

它不是"不必要的",因为Random类在内部存储了一些状态.这样做是为了确保如果您.Next()非常快速地调用多次(在相同的毫秒或刻度或其他情况下),您仍然不会得到相同的数字.

当然,如果在您的情况下这不是问题,您可以始终将这两行代码合并为一行:

new Random().Next(1, 100);
Run Code Online (Sandbox Code Playgroud)

  • 这很可能是像这样使用随机的问题...如果不是这样,它很快就会成为一个问题 - 如果有人实现这样的随机数生成器,因为它每50毫秒被调用一次并且它没有问题,它将会一旦硬件变得更快,很快就会中断,有人会花很多时间调试这个:) (5认同)
  • 是的是的,使用它来获得单个项目.从来没有.诱惑下来. (5认同)

小智 5

来自MSDN:随机类(系统):

"随机数生成从种子值开始.如果重复使用相同的种子,则生成相同的数字序列.产生不同序列的一种方法是使种子值与时间相关,从而产生不同的序列. Random的新实例.默认情况下,Random类的无参数构造函数使用系统时钟生成其种子值,而其参数化构造函数可以根据当前时间的滴答数采用Int32值.但是,因为时钟具有有限分辨率,使用无参数构造函数以紧密连续的方式创建不同的随机对象,创建随机数生成器,生成相同的随机数序列.以下示例说明了紧密连续实例化的两个随机对象生成相同的随机数序列. .."

维基百科解释了PRNG


naw*_*fal 5

你已经在这里得到了答案.重申正确的解决方案:

namespace mySpace
{
    public static class Util
    {
        private static Random rnd = new Random();
        public static int GetRandom()
        {
            return rnd.Next();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

所以你可以打电话:

var i = Util.GetRandom();
Run Code Online (Sandbox Code Playgroud)

一切都在.如果你真的需要一个真正的无状态静态方法来生成随机数,你可以依靠a Guid.

public static class Util
{
    public static int GetRandom()
    {
        return Guid.NewGuid().GetHashCode();
    }
}
Run Code Online (Sandbox Code Playgroud)

它会慢一点,但可能比任何时候都要多Random.Next,至少从我的经验来看.

不是:

new Random(Guid.NewGuid().GetHashCode()).Next();
Run Code Online (Sandbox Code Playgroud)

不必要的对象创建会使它变慢,特别是在循环中.

从未:

new Random().Next();
Run Code Online (Sandbox Code Playgroud)

不仅它的速度较慢(在一个循环内),它的随机性......根据我不是很好......

  • Guid.GetHashCode不保证任何类型的随机性.使用它是一场赌博.我想可以将它包装在一个美白功能中,例如`new Random` ... (2认同)
  • 您的第一个示例不是线程安全的。假设您有多个线程调用静态方法,就会遇到问题。`.Next()` [不是线程安全的,在并发使用下可能会抛出 IndexOutOfRange 异常](https://referencesource.microsoft.com/#mscorlib/system/random.cs,113)。 (2认同)

usr*_*usr 5

最好的方法是有一个ThreadStatic Random实例:

[ThreadStatic] static Random random;

Random Get() {
 if (random == null) random = new Random(Guid.NewGuid().GetHashCode());
 return random;
}
Run Code Online (Sandbox Code Playgroud)

这样就解决了一切问题

  1. 线程安全
  2. 表现
  3. 无需播种

我不明白为什么 .NET Framework(以及地球上的任何其他框架)不使用这种精神。