为什么序列化类中的Random实例重复生成相同的数字集?

JBe*_*Fat 7 c# random serialization

所以我是ac#noob.我有一个简单的问题,我找不到其他任何地方的答案.

 [Serializable()]
 public class Dictionary
 {
    private Random m_RandomGenerator = new Random();

    public int GetNext() 
    {
        return m_RandomGenerator.Next(100);
    }
 }
Run Code Online (Sandbox Code Playgroud)

Dictionary每个节目开始时间点被加载,而这个代码将返回完全相同的序列每次运行时数.我的意思是,每次运行可执行文件.当然它所播种的时间值应该是不同的(DateTime.Now.Ticks我假设?).

几点:

  • 只有一个Dictionary实例,在启动时从先前导出的文件中反序列化.
  • 如果我使m_RandomGenerator静态,那么问题就解决了.

有谁知道为什么?我仔细检查过我每次都没有创建一个新的Dictionary实例,所以这不是问题.


好吧,让我感到尴尬.事实证明,罪魁祸首是[Serializable()]属性.我使用的字典类是从先前导出的文件加载的,显然是将种子加载回Random().将变量更改为静态意味着不再从先前序列化的实例加载种子值 - 隐藏问题.

感谢所有提供建设性意见的人!

Aus*_*nen 6

(CW,因为这对评论来说太大了)

只有当种子播种时,此测试才会重复.您应该发布调用Dictionary的代码,因为那里可能存在一些可疑的东西(假设发布的代码是实际的代码),或者甚至更好地发布您自己的测试来重现问题.

[Test]
public void TestDictionary()
{
    var dictionary = new Dictionary();

    for(int i = 0; i < 10; i++)
    {
        Console.WriteLine(dictionary.GetNext());
    }
}

[Serializable]  // added after the fact
public class Dictionary
{
    //private Random m_RandomGenerator = new Random(12);
    private Random m_RandomGenerator = new Random();

    public int GetNext()
    {
        return m_RandomGenerator.Next(100);
    }
}
Run Code Online (Sandbox Code Playgroud)

这个测试确实会重复你的结果,但这是因为答案在这里:

[Test]
public void TestDictionary2()
{
    var alpha = new Dictionary();
    var bravo = new Dictionary();

    for(int i = 0; i < 10; i++)
    {
        Console.WriteLine("{0} - {1}", alpha.GetNext(), bravo.GetNext());
    }
}
Run Code Online (Sandbox Code Playgroud)

为了完整起见,这是一个序列化测试:

[Test]
public void SerializationPerhaps()
{
    var charlie = new Dictionary();
    Dictionary delta = null;

    // Borrowed from MSDN:  http://msdn.microsoft.com/en-us/library/system.serializableattribute.aspx

    //Opens a file and serializes the object into it in binary format.
    using (var stream = File.Open("data.xml", FileMode.Create))
    {
        var formatter = new BinaryFormatter();
        formatter.Serialize(stream, charlie);
    }


    //Opens file "data.xml" and deserializes the object from it.
    using (var stream = File.Open("data.xml", FileMode.Open))
    {
        var formatter = new BinaryFormatter();

        delta = (Dictionary) formatter.Deserialize(stream);
        stream.Close();
    }

    for(int i = 0; i < 10; i++)
    {
        Assert.AreEqual(charlie.GetNext(), delta.GetNext());
    }
}
Run Code Online (Sandbox Code Playgroud)