Random sometimes, not random other times
From a email:
private void button1_Click(object sender, EventArgs e)
{
Customer c = new Customer();
c.Randomize();
Customer b = new Customer();
b.Randomize();
MessageBox.Show(string.Format(
“object c random number = {0}, object b random number = {1}”,
c.RandomNumber, b.RandomNumber));
}
public class Customer
{
private int random = 0;
public void Randomize()
{
Random r = new Random();
random = r.Next();
}
public int RandomNumber
{
get { return random; }
}
}
If I run the above code without debugging it always returns the same random number, but if I step through the code I get different random numbers.
******
This is a variant of a question that comes up fairly often.
When you create an instance of the Random class, the pseudo-random number generator needs to be seeded with an initial value. Some generators always seed with zero, which means you always get the same sequence of numbers. The .NET Random class seeds using the time, which means you get different results from run to run without having to set the seed yourself.
It also means, however, that if you create two Random instances one right after another, the seed value (I think it uses GetTickCount()) hasn’t had time to change, and you get the same sequence. But if you run it in the debugger, enough time passes between the creation of the two instances that you get different seeds and different numbers.
I think the best solution here is to move the Random instance to a static field:
static Random r = new Random();
And then just use that instance of Random from all the Customer instances.
Rule of thumb… call Randomize() as FEW times as possible.
There’s a problem with making the Random instance static: the Random class isn’t threadsafe.
I’ve written a small wrapper class in my miscellaneous utility library (linked above) which allows static calls which lock round a single instance. This makes the calling threadsafe and means you never need your own Random instance unless you specifically want to use a particular seed.
I originally tried having a lock-free version with a Random instance per thread – this was significantly slower than putting a lock round the calls, at least on every system I tried it on.
Jonm
I’m new to C# (which I like very much, coming from a VB background) and having the precise issue described. However, when I change:
private int randomRoll(int min, int max)
{
// Create new Random class
Random numRange = new Random(DateTime.Now.Millisecond);
int randRoll = numRange.Next(min,max+1);
return randRoll;
}
to private int randomRoll(int min, int max)
{
// Create new Random class
static Random numRange = new Random(DateTime.Now.Millisecond);
int randRoll = numRange.Next(min,max+1);
return randRoll;
}
I receive a compile error "The modifier ‘static’ is not valid for this item."
Can you point out what I’m missing?
-Erin
Erin,
Static is no allowed on local variables. What you need to do is put:
static Random numRange = new Random();
in the section of your class where you define fields.
You also don’t need to pass in a parameter – Random() will automatically seed based on the time.
PingBack from http://woodtvstand.info/story.php?id=88395