c# - 为什么这段代码会为两个方法调用产生相同的输出?

标签 c# static

为什么这段代码对两个方法调用产生相同的输出?我会假设因为一个方法是一个普通的公共(public)方法并且是从一个实例调用的,所以它会为静态方法调用生成一个不同的随机数,因为该实例与为静态方法调用创建的实例是分开的?

class ClassWithStaticMembers
{

    public static int ReturnAnIntStatic()
    {
        Random random = new Random();
        return random.Next();
    }

    public int ReturnAnInt()
    {
        Random random = new Random();
        return random.Next();
    }
}

class Program
{

    static void Main(string[] args)
    {

        ClassWithStaticMembers classWithStaticMembers = new ClassWithStaticMembers();

        //We can do this because the method is declared static. 
        Console.WriteLine(ClassWithStaticMembers.ReturnAnIntStatic());

        //This can be used as we have not declared this method static
        Console.WriteLine(classWithStaticMembers.ReturnAnInt());

        Console.ReadKey();

}

输出如下:

12055544 12055544

有人可以解释为什么使用来自类实例的方法调用会产生与来自静态方法的方法调用相同的结果吗?为方法调用生成的实例是否不同?

编辑:除此之外。是 ClassWithStaticMembers 的实例,用于调用独立于静态调用的公共(public)方法。我的意思是,如果编译器识别出我稍后在文件中调用同一个类,它会再次使用同一个实例吗?

最佳答案

那是因为 Random默认情况下由当前报价播种,并且由于这两种方法几乎同时被调用,它们将产生相同的数字。这在 documentation 中有解释。 :

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. This problem can be avoided by using a single Random object to generate all random numbers. 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. For more information, see the Random(Int32) constructor.

在两个方法调用之间暂停一下以观察差异:

Console.WriteLine(ClassWithStaticMembers.ReturnAnIntStatic());
Thread.Sleep(2000);
Console.WriteLine(classWithStaticMembers.ReturnAnInt());

或者为 Random 类使用不同的构造函数以不同方式播种它们。或者简单地使用 Random 类的相同静态实例:

class ClassWithStaticMembers
{
    private static Random random = new Random();

    public static int ReturnAnIntStatic()
    {
        return random.Next();
    }

    public int ReturnAnInt()
    {
        return random.Next();
    }
}

class Program
{

    static void Main()
    {
        var classWithStaticMembers = new ClassWithStaticMembers();
        Console.WriteLine(ClassWithStaticMembers.ReturnAnIntStatic());
        Console.WriteLine(classWithStaticMembers.ReturnAnInt());
        Console.ReadKey();
    }
}

这就是为什么当您需要真正的随机性而不是伪随机数时,您永远不应该使用 Random 类的原因。例如在密码学中你应该使用 RNGCryptoServiceProvider而不是 Random 类。一旦您知道用于实例化 Random 类的初始种子值,您就可以预测该类将要生成的所有数字。

关于c# - 为什么这段代码会为两个方法调用产生相同的输出?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9416973/

相关文章:

c# - C#中构造函数内部的静态成员

c# - 在另一个线程中捕获异常c#

c# - 找出 USB 连接来自哪个端口

c# - 获取独占进程句柄

c# - 如何在c#中实现一个循序渐进的按钮?

java - 多线程编程和递增静态变量

java - 通过对象在静态方法上使用非静态变量? java

c++ - 确保c++中静态变量的构造和销毁顺序

java - 类加载、静态 block

c# - 具有功能方法的枚举(组合类/枚举)