![](/img/trans.png)
[英]What internal algorithm does C# use to generate random number using Next method of Random class instance?
[英]C# Generate random numbers, while using library, that use internal Random instance
为了确保不同的随机数,您应该仅使用Random
类的一个实例,如此处 , 此处和此处的答案所建议。
在我的库中,我需要随机数,因此我创建了一个类Randomizer
,该类提供了使用单个Random
实例返回随机数的方法。 这是Randomizer
代码的一部分:
class Randomizer
{
private Randomizer() { }
public static Randomizer Instance { get; } = new Randomizer();
private static readonly Random random = new Random();
private static readonly object syncLock = new object();
public int Next(int minValue, int maxValue)
{
lock(syncLock)
{
return random.Next(minValue, maxValue);
}
}
// rest of code
}
现在,如果我的图书馆用户也需要随机数怎么办? 我应该公开我的Randomizer
类并在库的文档中指定用户应该使用我的Randomizer
类来生成随机数吗?
为了确保不同的随机数,您应该只使用Random类的一个实例
那不是很正确。 创建多个Random
实例非常好,只要您不要在紧凑的循环中初始化它们(因为它们是在当前时间播种的,因此您希望实例化时每个实例的当前时间都不同) 。
当您创建一个仅创建一个Random
对象并重用它的静态类时,就可以了。 从理论上讲,您的库的调用者可以创建自己的静态Random
,该静态Random
是同时创建的,因此它们的生成器将与您的生成器获得相同的种子,并因此获得相同的随机数序列。 由于创建静态类需要花费时间,因此可能不会发生。 除非有一定的原因,否则在呼叫者的序列和您的序列之间的相关性很重要,反正这也可能无关紧要。
您为什么要用自己的实现负担图书馆的使用者?
如果它是内部的,因为您需要一个非常特定的随机提供程序来提供库的内部运行。 如果在与库交互时不需要外部使用者也遵守您在代码中强加的规则,则不要公开生成器,如果需要的话,让用户使用自己的Random
。
另一方面,如果您需要使用者在与库的公共API交互时使用特定的随机数生成器,则需要公开公开该类。
通过使用保证为随机的显式种子(例如,从操作系统中获取一个)来初始化您的Random对象。 这样,用户是否创建自己的Random实例都没有关系,并且您无需考虑将对Next
方法的调用与用户代码进行同步。
但是,如果您无法获得随机种子,则一种解决方案是定义一个接口,并让您的库用户向需要随机数的每个组件注入一个实例:
public interface IRandomizer
{
int Next(int minValue, int maxValue);
}
该接口的约定必须定义您的库的确切需求(例如, Next
方法必须是线程安全的)。 您的Randomizer类可以实现此接口,以用作默认实现。
例如,密钥生成器库组件可以提供两个构造函数:
public class KeyGenerator
{
private IRandomizer randomizer;
public KeyGenerator(IRandomizer randomizer)
{
// instance will use the specified IRandomizer
this.randomizer = randomizer;
}
public KeyGenerator()
{
// instance will use your Randomizer class.
this.randomizer = Randomizer.Instance;
}
}
这样,您的图书馆用户就可以决定是要提供自己的随机数生成器,还是要使用图书馆的默认值。
我将使用以下方法:
public interface IRandomizer
{
int Next(int inclusiveLower, int exclusiveOuter);
}
然后,我将公开一个带有默认实现的静态类,以及一个可选的工厂方法,以创建特定的“种子”实例。 请注意,内部使用的生成器( Default
)是公开可访问的,但完全可以完全是内部使用的:
//Note, the following code is an outline of the general idea
public static class RandomGenerator
{
private readonly static Lazy<Randomizer> inner = new Lazy<Randomizer>();
public static IRandomizer Default { get { return inner.Value; } }
public static IRandomizer CreateNew(Random seed)
{
return new Randomizer(seed);
}
private class Randomizer : IRandomizer
{
private readonly Random random;
private readonly object syncLock = new object();
public Randomizer(Random seed = null)
{
random = seed ?? new Random();
}
public int Next(int minValue, int maxValue)
{
lock (syncLock)
{
return random.Next(minValue, maxValue);
}
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.