2

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.

Community
  • 1
  • 1
Dave Bish
  • 19,263
  • 7
  • 46
  • 63
  • 2
    `Random` is a class. How would you have a global generator that spans machines, app domains etc...? – Oded May 22 '12 at 09:49
  • Possible duplicate question, http://stackoverflow.com/questions/4933823/class-system-random-why-not-static – M Afifi May 22 '12 at 09:55
  • The initialization of `Random` may have overhead that one should not suffer unless they intend to use it. – Jon May 22 '12 at 09:55
  • 1
    You could just have one statically managed per app-domain. – Dave Bish May 22 '12 at 09:58
  • 1
    In general, *programming frameworks* are I would say entitled to assume that the user - a programmer! - knows what they're doing. .NET is in many ways an easier world to get things 'right by default' in than Winapi was, but that basic assumption is still in place. – AakashM May 22 '12 at 10:07
  • 1
    @AakashM Obviously you're right - but programming frameworks should also make design decisions to help programmers avoid common pitfalls, like this one :D – Dave Bish May 22 '12 at 10:13

2 Answers2

5

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.

Matzi
  • 13,770
  • 4
  • 33
  • 50
5

.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; } }
}
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • Sure - that fine. I guess my question could be refined to: why is the *default* behaviour the more esoteric choice. – Dave Bish May 22 '12 at 09:57
  • 1
    @DaveBish My guess is as good as anyone else's, but I suspect that it is done to force programmers to make a conscious choice of a shared instance: once this choice is made, it is difficult to go back to multiple instances, so the architects of .NET did not wanted to make this choice for the programmers. – Sergey Kalinichenko May 22 '12 at 10:04
  • 3
    A warning to anybody who's tempted to copy your example code verbatim... The `Random` class isn't threadsafe so anybody using `RandomHelper` in a multi-threaded environment -- eg, ASP.NET -- will likely get horribly broken results. (I'm guessing that you already know this, but I'm also pretty sure that others don't know it.) – LukeH May 22 '12 at 10:25
  • @LukeH: It's also worth noting that the fact that a typical pseudo-random generator won't be threadsafe without explicit locking or other such mechanisms means that it will be faster to have two threads each create and use their own pseudo-random generator than to have one static generator which is shared among threads. – supercat Nov 15 '13 at 18:52