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

本文关键字:方式 实现 Net Random 为什么 | 更新日期: 2023-09-27 18:35:07

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

在 C# 中使用介于 0-9 之间的 UNIQE 随机数填充数组

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

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

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方法的好处?

编辑:我知道控制种子很重要 - 但是,默认情况下强制执行这似乎是奇怪的选择。如果有人想控制种子,他们很可能知道自己在做什么。

干杯。

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

因为这样你可以控制多个随机生成源。通过为每个实例设置相同的种子,您可以根据需要生成相同的序列。有时你不希望其他操作影响你的数字流。

想想一个游戏

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

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

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

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

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