So I'm a c# noob. I have a quick question that I can't find an answer to anywhere else.
[Serializable()]
public class Dictionary
{
private Random m_RandomGenerator = new Random();
public int GetNext()
{
return m_RandomGenerator.Next(100);
}
}
The Dictionary
instance is loaded each time the program starts, and this code will return the exact same sequence of numbers each time it is run. By which I mean, each time the executable is run. Surely the time value it's seeded with should be different (DateTime.Now.Ticks I assume?).
A couple of points:
- There is only one instance of Dictionary, deserialized from a previously-exported file开发者_如何学C at startup.
- If I make m_RandomGenerator static then the problem is fixed.
Does anyone know why? I did double check that I'm not creating a new instance of Dictionary each time, so that's not the issue.
Well, colour me embarrassed. As it turns out the culprit was the [Serializable()] attribute. The dictionary class I was using was loaded from a previously exported file, which was obviously loading the seed back into Random(). Changing the variable to static meant that the seed value was no longer loaded from the previously serialised instance - hiding the issue.
Thanks to all the people offering constructive advice!
(CW because this is way too big for a comment)
This test will only ever repeat when Random is seeded. You should post the code calling Dictionary because there may be something fishy there (assuming the code posted is the actual code) or even better post your own test that reproduces the issue.
[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);
}
}
This test does repeat your results but that's because of the answer here:
[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());
}
}
For completeness, here's a serialization test:
[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());
}
}
The source of your problem must be somwhere else than in the code you posted. Here is the same code, embedded in a test harness:
using System;
namespace RandomTest
{
public class Dictionary
{
private Random m_RandomGenerator = new Random();
public int GetNext()
{
return m_RandomGenerator.Next(100);
}
}
class Program
{
static void Main(string[] args)
{
Dictionary d = new Dictionary();
for (int i=0;i<10;i++)
{
int r = d.GetNext();
Console.Write("{0} ",r);
}
Console.WriteLine();
}
}
}
It returns a different sequence every time it is run.
Well without further code samples the answer to your question is simple.
It is not repetitive.
I plugged your code sample into a console application and the result is completely random.
namespace Sandbox
{
class Program
{
static void Main(string[] args)
{
Dictionary dict = new Dictionary();
for (int count = 0; count < 100; count++)
Console.WriteLine(dict.GetNext());
Console.ReadLine();
}
}
public class Dictionary
{
private Random m_RandomGenerator = new Random();
public int GetNext()
{
return m_RandomGenerator.Next(100);
}
}
}
Result:
http://www.codetunnel.com/content/images/random.jpg
I don't know this is what you exactly want but this help me to solve my problem. Your post and other answer, comments bring me to this.
using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
namespace SerializeRandom
{
[Serializable] // added after the fact
public class RandomGenerator
{
const string fileName = "random.bin";
private Random random = new Random();
public int GetNext()
{
return random.Next(100);
}
public static void Save(RandomGenerator obj)
{
using (var stream = File.Open(fileName, FileMode.Create))
{
var formatter = new BinaryFormatter();
formatter.Serialize(stream, obj);
}
}
public static RandomGenerator Load()
{
RandomGenerator randomGenerator = null;
//create new object if file not exist
if (!File.Exists(fileName))
{
randomGenerator = new RandomGenerator();
}
else
{
//load from bin file
using (var stream = File.Open(fileName, FileMode.Open))
{
var formatter = new BinaryFormatter();
randomGenerator = (RandomGenerator)formatter.Deserialize(stream);
stream.Close();
}
}
return randomGenerator;
}
}
}
and test class
using System.Collections.Generic;
using NUnit.Framework;
namespace SerializeRandom
{
public class RandomGeneratorTest
{
[Test]
public void TestDictionary1()
{
var randomGenerator = RandomGenerator.Load();
var randomResult1 = new List<int>();
for (int i = 0; i < 10; i++)
{
randomResult1.Add(randomGenerator.GetNext());
}
RandomGenerator.Save(randomGenerator);
randomGenerator = RandomGenerator.Load();
var randomResult2 = new List<int>();
for (int i = 0; i < 10; i++)
{
randomResult2.Add(randomGenerator.GetNext());
}
CollectionAssert.AreNotEqual(randomResult1, randomResult2);
}
}
}
Thats because it (Random())
is a pseudorandom number generator.
A seed is required to initialize the random number generator to make it not repetitive.
An acceptable choice is to use the computer time as the seed.
However, because the clock has finite resolution, using the parameterless constructor to create different Random objects in close succession creates random number generators that produce identical sequences of random numbers.
http://msdn.microsoft.com/en-us/library/system.random.aspx
I'd be careful with the default constructor with no parameters.
精彩评论