0

Possible Duplicate:
Random number generator only generating one random number
class System.Random .. why not static?

I have a public static class called RandomGeneratorwhich only has one value a public static random = new Random();

This is what it looks like

    public static class RandomGenerator
    {
        public static Random random = new Random(); 
    }

I had to do this because when my code went to access a random it would generate too many duplicate copies (I believe it had something to do with the location of Random in memory)

The above code works great! My code generates a truly random value each time it's called. My question is why isn't random a built in static function of the C# language? Is it because accessing something this way will result in a performance hit? Are there any notable performance issues with the way i've written my code?

Community
  • 1
  • 1
Josh Siegl
  • 735
  • 1
  • 9
  • 16
  • 2
    Off topic: It appears that every other time someone encounters a design decision they don't understand and ask SO about, "performance" is their best guess. **Why?** –  Dec 27 '12 at 08:55
  • 1
    To be more specific it returns an instance of `Random` every time it is called. To get a random value, you don't need to create a new instance. Just call one of the `Next` methods – Brian Rasmussen Dec 27 '12 at 08:55
  • @delnan, could be because it is the only obvious problem with code when one starts... I.e. the fact that static methods/properties are very painful to test (and as result may lead to performance issues) is much harder to just expect, while everyone see programs that are slow... – Alexei Levenkov Dec 27 '12 at 09:02
  • @AlexeiLevenkov But it's not just about `static`, or any other single problem. It's everywhere. Everyone's doing APIs like this, should I too? Surely there's an important difference in performance. -- Why does C++ require semicolons? Is it for performance? -- Why are circles round? Does it help performance? –  Dec 27 '12 at 09:05
  • @delnan That was uncalled for. I do in fact understand the design aspect behind WHY I would want to do something like this, as I explained in my question. What I didn't understand was why there wasn't a class that did this for me in C#, and I speculated that it might have been because it caused some type of performance issue. I now know this is not the case thanks to the more helpful members of SO. Thank you for your completely unconstructive comment, it has been flagged. – Josh Siegl Dec 27 '12 at 09:34
  • @JoshSiegl Let's stay constructive. I do not intend to belittle, insult, or otherwise offend you. I am just bewildered by a recurring theme I'm seeing a lot, not just here, so I asked. I did not (and still don't) see any speculation as to other reasons why `Random` isn't static and no `static Random` instance is provided in your question. Apart from the question about performance problems, of course. –  Dec 27 '12 at 09:40

3 Answers3

6

MSDN writes the following about the Random constructor:

The default seed value is derived from the system clock and has finite resolution. As a result, different Random objects that are created in close succession by a call to the default constructor will have identical default seed values and, therefore, will produce identical sets of random numbers. This problem can be avoided by using a single Random object to generate all random numbers. You can also work around it by modifying the seed value returned by the system clock and then explicitly providing this new seed value to the Random(Int32) constructor.

http://msdn.microsoft.com/en-us/library/h343ddh9.aspx

Saw
  • 6,199
  • 11
  • 53
  • 104
Tamás Varga
  • 118
  • 3
  • I should have looked at the MSDN documentation, it'll be my first stop next time. This is exactly what I was looking for, thank you. – Josh Siegl Dec 27 '12 at 09:00
2

The problem you're describing has nothing to do with random being or not being static. I suppose you were creating Random instance and then getting random value from this instance. This way every Random was created with default seed which is current time with seconds accuracy. During the time of single seconds you were getting same values since Random instance were created with same seed.

empi
  • 15,755
  • 8
  • 62
  • 78
2

It's not natively static because "random" numbers in .Net aren't truly random - they're "psuedo-random", meaning they're random enough for statistics, but not random enough for cryptography. That is, they're evenly distributed across a range, but given the seed parameters, you can predict what the next "random" value will be. That's why you have to instantiate the Random class (like you're doing above) to get a random number - you need to create a new instance, seed it (which it does using the current timestamp, if you don't manually seed it), and then get the "Next" random value. If you seed the Random class with the same value, it will yield the same series of "Random" numbers - using the system time as the seed is pretty effective, as it's always changing, but it's guessable pretty easily.

Having a static "Random" class like this is one way to get a random value without instantiating a new object every time you need it, but all you're doing here is instantiating a new copy anyway. A way to do this more effectively might be something like:

class RandomNumber { static readonly Random r = new Random();

    public static Int32 GetNext(int maxValue)
    {
        return r.Next(maxValue);
    }

    public static Int32 GetNext()
    {
        return r.Next();
    }
}

This way, you're only instantiating once, and you'll continue to reuse that instance - each time you want a new random number, just call the GetNext method on the static class (either specifying an upper bound or not), and you'll get a new number.

SqlRyan
  • 33,116
  • 33
  • 114
  • 199
  • (1) How is them being PRNGs a reason to be not static? (2) You appear to contradict yourself. You present that issue as reason `Random` isn't static, yet go on to say is a way around the issue (and fail to name any other downsides). –  Dec 27 '12 at 09:03
  • Random isn't static by itself, it's instantiated - I'll clarify my answer. – SqlRyan Dec 27 '12 at 09:06
  • I don't think *that* part is unclear. –  Dec 27 '12 at 09:06
  • @delnan: Maybe this is where my design knowledge breaks down - I've always felt like "Random" isn't static to force developers to acknowledge the non-randomness of it, but maybe that's not the case and there's some other reason for that design decision. In class VB, you could just use Rand and it would fetch a new random number, though you had the option to manually seed the generator (I know that's not a perfect example) - why the change into .NET? Since Random seeds itself with the system time anyways, why can't it just be available as a static, natively doing what's being done here? – SqlRyan Dec 27 '12 at 09:25
  • I don't see how it being static or not would change anything about perception of the pseudo-randomness. I suspect very different reasons: If it's static, everyone in the entire universe (well, process) is sharing the same stream of PRNGs. Want to use two independent streams? Needs pseudo-random numbers in a library and don't want to disrupt client code's randomness needs? And so on. Why make something global that isn't global? Making the PRNG static is about as meaningful as making `StreamReader` static. It's completely unnecessary global state. –  Dec 27 '12 at 09:31