为什么Random()在.Net中以这种方式实现?

时间:2012-05-22 09:47:43

标签: c# .net random

我最近在这里回答了一个问题,该问题由成员@dtb编辑。

filling a array with uniqe random numbers between 0-9 in c#

问题涉及使用Random() - 并且说成员编辑了我的答案以避免这个common pitfall(正如他所说)

我的原始代码不容易受到此问题的影响,如下所示:

public void DoStuff()
{
    var rand = new Random();
    while() {} //Inner loop that uses 'rand'
}

答案被编辑了,因为看起来意图是在循环中调用函数 - 这会使代码容易受到攻击 - 它本质上被改为:

public void DoStuff(Random R)
{
    while() {} //Inner loop that uses 'rand'
}

我的直接想法是 - 这只是将Random实例的负担推到了堆栈中 - 如果有问题的程序员不理解它是如何实现的,那么它们仍然会陷入这个陷阱。

我想我的问题是 - 为什么.Net中的Random()实现方式与Javascript相同 - 例如 - 使用一个静态的全局Random()(比如,每个AppDomain?)? 当然,在极少数需要控制种子的情况下,您仍然可以提供更明确的重载/方法,将当前时间用作种子。

这肯定会避免这种常见的陷阱。任何人都可以启发我关于.Net方法的好处吗?

编辑:我理解控制种子非常重要 - 但是,通过默认强制执行此操作似乎是一个奇怪的选择。如果有人想控制种子,他们很可能知道他们在做什么。

干杯。

2 个答案:

答案 0 :(得分:5)

因为这种方式可以控制多个随机生成源。通过为每个实例设置相同的种子,您可以生成相同的序列(如果需要)。有时你不希望其他行为影响你的数字流。

想想游戏:每个随机都是从种子编号生成的,所以如果你保存玩家输入和随机种子,你可以从头到尾重现整个游戏。但如果你生成随机的,例如在游戏过程中,粒子或其他不相关但随机的东西,你也不想保存它们。最简单的方法是声明两个随机的,一个用于重要的事情,另一个用于永久的其他事情。但这只是一个例子。

因此,您可以根据自己的需要自由声明随机序列,如果您想以这种方式使用它,则无需使用技巧。

答案 1 :(得分:5)

.NET解决方案比涉及单个全局生成器的解决方案更灵活。它允许应用程序的每个部分创建和使用可重复伪随机数的独立序列,这对于调试目的至关重要。调试依赖于伪随机数的代码并不开心;当从代码的不同部分访问相同的生成器时,就不可能了。

同时,如果您想拥有Random的共享实例,只需几行代码就可以轻松地将其提供给您的应用程序:

// !!! This is not thread safe!!!
static class RandomHelper {
    private static readonly Random rnd = new Random();
    public static Random Instance {get { return rnd; } }
}