Reputation: 19636
I recently answered a question on here, which was edited by member @dtb.
filling a array with uniqe random numbers between 0-9 in c#
The question involved the use of Random() - and said member had edited my answer to avoid this common pitfall (as he put it)
My original code wasn't vulnerable to this issue in isolation, as was as follows:
public void DoStuff()
{
var rand = new Random();
while() {} //Inner loop that uses 'rand'
}
The answer was edited, as it appeared the intent was to call the function in a loop - which would have made the code vulnerable - it was changed to essentially:
public void DoStuff(Random R)
{
while() {} //Inner loop that uses 'rand'
}
My immediate thought was - this just pushed the burden of maintaining the Random instance further up the stack - and if the programmer in question doen't understand how it is implemented, they'll still fall into this pitfall.
I guess my question is - why isn't Random() in .Net implemented in the same way as it is in Javascript, for example - with one static, global Random() (Say, per AppDomain?)? Naturally, you could still provide more explicit overloads/methods that use the current time as a seed, for the very rare cases when you need to control the seed.
Surely this would avoid this very common pitfall. Can anyone enlighten me as to the benifits of the .Net approach?
EDIT: I understand that taking control of the seed is important - however, enforcing this by default seems to be the weird choice. If someone wants to take control of the seed, it's likely they know what they're doing.
Cheers.
Upvotes: 2
Views: 502
Reputation: 726479
.NET solution is more flexible than one involving a single global generator. It lets each part of your application to create and use independent sequences of repeatable pseudorandom numbers, which is vital for debugging purposes. Debugging code that relies on pseudorandom numbers is no fun to start with; when the same generator is accessed from different parts of the code, it becomes impossible.
At the same time, if you want to have a shared instance of Random
, you can easily make it available to your application with just a few lines of code:
// !!! This is not thread safe!!!
static class RandomHelper {
private static readonly Random rnd = new Random();
public static Random Instance {get { return rnd; } }
}
Upvotes: 5
Reputation: 13925
Because this way you can control multiple random generation source. By setting the same seed to each instance, you can generate the same sequence, if you need that. And sometime you don't want that other actions affect your flow of numbers.
Think a game: every random is generated from a seed number, so if you save the player input, and the random seed, you can reproduce the whole game, from beginning to end. But if you generate random e.g. particles, or other irrelevant but random stuff during the play, you don't want to save those, too. The easiest way is to declare two random, one for the important things and an other for everithing else. But this is just one example.
So you have the freedom to declare the random sequenc based on your need, and you need not to use tricks if you want to use it this way.
Upvotes: 5