简体   繁体   English

每次调用构造函数时,如何使C#随机数生成器更改?

[英]How do I make my C# random number generator change with each time the constructor is called?

I have two classes, a Teacher class and a Student class. 我有两个班,一个教师班和一个班级班。 In my program I create an array of 10 Teacher objects and within each Teacher object is an array of 10 Student Objects. 在我的程序中,我创建了一个包含10个Teacher对象的数组,每个Teacher对象中有一个包含10个Student对象的数组。 Each Student object also has an array of integers as a member variabe, and when each Student is instantiated, it's own array of integers are filled with numbers from a random number generator. 每个Student对象还有一个整数数组作为成员变量,当每个Student被实例化时,它自己的整数数组都用随机数生成器中的数字填充。 My program goes something like this: 我的程序是这样的:

  • An array of type Teacher is created with size 10 创建一个类型为Teacher的数组,大小为10
  • The array is then filled with 10 actual teacher objects 然后用10个实际的教师对象填充该数组
  • Each Teacher object contains an array of Student objects of size 10 as a member variable 每个Teacher对象都包含一个大小为10的Student对象数组作为成员变量
  • The Student array in each Teacher object is filled with actual Student objects 每个Teacher对象中的Student数组都填充了实际的Student对象
  • Each student object has an array of integers that are filled with random numbers in the Student objects constructor. 每个学生对象都有一个整数数组,在Student对象构造函数中填充了随机数。

Here is the problem I ran into: It seems that every time the 10 Student objects are created for each Teacher, the random number generator within the Student object constructor does not reset or change even when I call the .Next() function until the next set of 10 Student objects are created for the next Teacher object. 这是我遇到的问题:似乎每次为每个教师创建10个Student对象时,即使我调用.Next()函数直到下一个,Student对象构造函数中的随机数生成器也不会重置或更改为下一个Teacher对象创建10个Student对象。 What I want is the 10 Teacher objects to each have their own Student Objects which have their own integer arrays filled with randomly generated numbers. 我想要的是10个教师对象,每个对象都有自己的学生对象,这些对象有自己的整数数组,里面填充了随机生成的数字。

Any help would be appreciated! 任何帮助,将不胜感激! I ran into this sort of problem with constructors with my last question, and that was a matter of whether something was to be static or not and I'm not sure that's the case this time. 在我的最后一个问题中,我遇到了构造函数的这种问题,这是一个问题是否是静态的,我不确定这次是什么情况。 Please ask me questions if I wasn't clear enough about anything!! 如果我对任何事情都不够清楚,请问我问题!

UPDATE** So after looking at MSDN, I found in their sample code "Thread.Sleep(2000)" and stuck it into my Student Constructor just to see what it did. 更新**所以在查看MSDN之后,我在他们的示例代码“Thread.Sleep(2000)”中找到并将其粘贴到我的学生构造函数中,只是为了看看它做了什么。 It seemed to have solved the problem although my program runs a lot slower now, is there a minimum sleep value to wait until the Random.Next() uses a new seed from the clock and even if I did solve the problem, is there a better way to do this? 它似乎已经解决了问题,虽然我的程序现在运行得慢很多,是否有一个最小的睡眠值要等到Random.Next()使用来自时钟的新种子,即使我确实解决了问题,是否有更好的方法吗? My random number generator is already a static member variable of Student. 我的随机数生成器已经是Student的静态成员变量。

If you initialize several Random instances using the default constructor, Random() , within a short time period, then you risk that they would end up with the same seed value (which is time-dependant) and, therefore, generate the same random sequence each time. 如果使用默认构造函数Random()在短时间内初始化几个Random实例,则可能会导致它们最终具有相同的种子值(这取决于时间),因此会生成相同的随机序列每一次。

You can fix this issue by initializing a single static Random instance, and share it among all Student instances. 您可以通过初始化单个静态Random实例来解决此问题,并在所有Student实例之间共享它。 This is perfectly safe as long as you're not multi-threading. 只要您不是多线程,这是非常安全的。

public class Student
{
    private static readonly Random random = new Random();        
}

From the MSDN page on the Random() constructor: Random()构造函数的MSDN页面:

The default seed value is derived from the system clock and has finite resolution. 默认种子值源自系统时钟并具有有限的分辨率。 As a result, different Random objects that are created in close succession by a call to the default constructor will have identical default seed values and, therefore, will produce identical sets of random numbers. 因此,通过调用默认构造函数紧密连续创建的不同Random对象将具有相同的默认种子值,因此将生成相同的随机数集。 This problem can be avoided by using a single Random object to generate all random numbers. 使用单个Random对象生成所有随机数可以避免此问题。 You can also work around it by modifying the seed value returned by the system clock and then explicitly providing this new seed value to the Random(Int32) constructor. 您还可以通过修改系统时钟返回的种子值,然后将此新种子值显式提供给Random(Int32)构造函数来解决此问题。 For more information, see the Random(Int32) constructor. 有关更多信息,请参阅Random(Int32)构造函数。

Edit : Although you state that your random number generator is already a static member, this is still not enough if you're instantiating it repeatedly (redundantly) during each Student initialization. 编辑 :虽然您声明您的随机数生成器已经是静态成员,但如果您在每次Student初始化期间重复(冗余地)实例化它,这仍然是不够的。 The following code is still incorrect : 以下代码仍然不正确

public class Student
{
    private static Random random;

    private int[] numbers;

    public Student()
    {
        random = new Random();
        numbers = new int[10];
        for (int i = 0; i < 10; ++i)
            numbers[i] = random.Next();
    }
}

You need to replace it with a version that only instantiates Random once, like so: 您需要将其替换为仅实例化Random一次的版本,如下所示:

public class Student
{
    private static readonly Random random = new Random();

    private int[] numbers;

    public Student()
    {
        numbers = new int[10];
        for (int i = 0; i < 10; ++i)
            numbers[i] = random.Next();
    }
}

A common pitfall with Random is to create a new instance each time you need a random value. Random的常见缺陷是每次需要随机值时都要创建一个新实例。

for (int i = 0; i < 1000; i++) {
   var random = new Random();
   list.Add(random.Next());
}

This does not work as expected, since Random uses the actual time to create the first random value. 这不能按预期工作,因为Random使用实际时间来创建第一个随机值。 However, the time clock has a limited resolution. 但是,时钟的分辨率有限。 It can be that several succeeding iterations return the same time and thus the same (pseudo) random value! 可能是几个连续的迭代返回相同的时间,因此返回相同的(伪)随机值!

The solution is to create random only once. 解决方案是只创建一次random

var random = new Random();
for (int i = 0; i < 1000; i++) {
   list.Add(random.Next());
}

You could also declare random as a static class member 您还可以将random声明为静态类成员

public static readonly Random RandomGenerator = new Random();

A random number generator uses the system time as a seed. 随机数生成器使用系统时间作为种子。 I wonder if you are possibly declaring a new generator and calling it before the system has time to move on to its next increment. 我想知道你是否可能在系统有时间进入下一个增量之前声明一个新的发生器并调用它。 The processor cycles are actually more than often faster than the system clock. 处理器周期实际上通常比系统时钟更快。 Can you post a code example? 你能发一个代码示例吗?

I would suggest declaring a Static generator as either a class property or somewhere else accessible, instantiate it as final. 我建议将静态生成器声明为类属性或其他可访问的属性,将其实例化为final。 This will guarantee that you wont be overwriting the generator with another. 这将保证您不会用另一个覆盖发电机。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM