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

Dav*_*ish 2 .net c# random

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

在c#中填充0-9之间的uniqe随机数的数组

问题涉及使用Random() - 并且该成员编辑了我的答案以避免这种常见的陷阱(正如他所说)

我的原始代码不容易孤立地受到这个问题的影响,如下所示:

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

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

public void DoStuff(Random R)
{
    while() {} //Inner loop that uses 'rand'
}
Run Code Online (Sandbox Code Playgroud)

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

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

当然,这将避免这种非常常见的陷阱.任何人都可以启发我关于.Net方法的好处吗?

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

干杯.

Mat*_*tzi 5

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

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

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


das*_*ght 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; } }
}
Run Code Online (Sandbox Code Playgroud)

  • 向任何想要逐字复制示例代码的人发出警告......"Random"类不是线程安全的,因此任何在多线程环境中使用`RandomHelper`的人 - 例如ASP.NET--都可能会受到严重破坏结果.(我猜你已经知道了,但我也很确定别人不知道.) (3认同)