The curious case of the non-random Random()
15 Mar 2009I was writing some code yesterday, and need to generate different “names” for objects. Rather than using Guid.NewGuid()
, I decided (for no clear reason) to append a random int generated by System.Random, with code looking something like that:
public string CreateRandomName()
{
Random randomizer = new Random();
return randomizer.Next().ToString();
}
All looked great, until I wrote code like this:
[Test]
public void CreateInstancesWithDifferentNames()
{
var firstInstance = new MyClass();
firstInstance.Name = CreateRandomName();
var secondInstance = new MyClass();
secondInstance.Name = CreateRandomName();
Assert.AreNotEqual(firstInstance.Name, secondInstance.Name);
}
I expected each instance to have a different name, but the test fails miserably. Both instances get a random number, but… they get the same random number.
What really threw me off was that the first thing I did was to add a breakpoint in the test to see what was going on - and every time I would step into the code, the test would pass. This sounded like a Schroedinger cat moment: by merely observing the system I was changing its behavior.
I believe I figured out the source of the problem. Of course, Random does not produce “random” numbers, but rather a pseudo-random series, generated from a seed value. When you use the empty constructor for Random(), the seed is set to a value based off the clock; and because my two calls were taking place so close from each other, the seed must have been set to the same value. I am not totally sure about this, but when I added a “delaying” loop in my code, everything worked fine:
[Test]
public void CreateInstancesWithDifferentNames()
{
var firstInstance = new MyClass();
firstInstance.Name = CreateRandomName();
for (int i = 0; i < 1000000; i++) { }
var secondInstance = new MyClass();
secondInstance.Name = CreateRandomName();
Assert.AreNotEqual(firstInstance.Name, secondInstance.Name);
}
The take-away of the story - be careful when using Random, because you might end up with surprisingly less randomness than what you expect…