33

Why do i need to create an instance of Random class, if i want to create a random number between 1 and 100 ....like

Random rand = new Random();
rand.Next(1,100);

Is there any static function of Random class to do the same? like...

Random.Next(1,100);

I don't want to create an instance unnecessarily

Sunil
  • 1,941
  • 3
  • 19
  • 25
  • 16
    And in conclusion ... *don't prematurely optimize* :-) –  Apr 15 '10 at 07:45
  • Possible duplicate of [Why is the System.Random class not static?](http://stackoverflow.com/questions/4933823/why-is-the-system-random-class-not-static) – Michael Freidgeim May 31 '16 at 01:46

11 Answers11

36

It is best practice to create a single instance of Random and use it throughout your program - otherwise the results may not be as random. This behavior is encouraged by not creating a static function.

You shouldn't worry about "creating an instance unnecessarily", the impact is negligible at best - this is the way the framework works.

Kobi
  • 135,331
  • 41
  • 252
  • 292
  • 13
    could that not be achieved if Random was static? The generator would be seeded at construction time and you could use it through-out? – Asher Apr 15 '10 at 07:45
  • 2
    @Asher - that would require an internal instance anyway, and require state. I don't think it belongs as part of the framework, but it could be implement easily on your static class. – Kobi Apr 15 '10 at 07:52
  • 2
    @Kobi maybe I should post my own question on this :). The memory usage and performance aside, I do find it annoying to instantiate this class. If you are just going to use one throughout, why not just make it static. Is this something about static classes I am not getting. Anyway, I digress – Asher Apr 15 '10 at 07:57
  • @Asher: now you can choose to use multiple independent RNGs, or choose to use a fixed seed if you want to use the same list of 'random' numbers. – Hans Kesting Apr 15 '10 at 08:00
  • 2
    Think about reusability - *you* think you call it just once, but one day maybe someone will call your function 1000 times, and you lose randomness. If you find instantiate class annoying, maybe C# isn't quite right for you :) – Kobi Apr 15 '10 at 08:00
  • @Asher - I didn't mean to offend, in any way - it's just that instantiating objects is a common task. – Kobi Apr 15 '10 at 08:04
  • 1
    @Kobi I meant instantiating this particular class. For me it's a bit like instantiating DateTime to get to Now. – Asher Apr 15 '10 at 08:07
  • 7
    @Asher : But Random isn't thread safe, so if you wanted calls to Random from multiple threads that wouldn't work... Besides what if you want multiple seeds for your Random classes? For example I want to use multiple threads that will yield the same results upon each execution, requires me to use multiple instances with the same seed, with a static it would be a race. – Ian Apr 15 '10 at 08:08
  • @Ian you right it's not. Thanks for clearing that up. Even though calling "Random" to generate the "same results" is counterintuitive. – Asher Apr 15 '10 at 08:35
  • @Asher: It's not that uncommon to want a series of values that are unpredictable but still repeatable. I find it quite handy in some of my unit tests. – Phil Gan Apr 15 '10 at 08:53
32
//Function to get random number
private static readonly Random random = new Random();
private static readonly object syncLock = new object();
public static int RandomNumber(int min, int max)
{
    lock(syncLock) { // synchronize
        return random.Next(min, max);
    }
}

Copied directly from

Community
  • 1
  • 1
Pratik Deoghare
  • 35,497
  • 30
  • 100
  • 146
  • 5
    This is pretty good at avoiding miss-use of the class as in Evgeny's answer. +1 for citing the code too, credit where it's due :) – Codesleuth Apr 15 '10 at 08:02
7

It's not "unnecessary", because the Random class stores some state internally. It does that to make sure that if you call .Next() multiple times very quickly (in the same millisecond or tick or whatever) you still won't get the same number.

Of course, if that's not a problem in your case you can always combine those two lines of code into one:

new Random().Next(1, 100);
EMP
  • 59,148
  • 53
  • 164
  • 220
  • 9
    it most probably is a problem to use Random like this...if it is not, it may become a problem soon - if someone implements random number generator like this because it gets called every 50 milliseconds and it works without a problem, it will break very soon as soon as the hardware gets faster and someone will spend A LOT of time debugging this :) – Marek Apr 15 '10 at 07:43
  • True, so I'd never use this sort of code in a loop - but if you know your program only needs to generate one random number then it's safe enough. – EMP Apr 15 '10 at 23:15
  • 5
    Yes yes yes, use this to get a single item. Never otherwise. Tempted to downvote. – nawfal Mar 31 '13 at 12:07
6

You already got answers here. Just reiterating the right solution:

namespace mySpace
{
    public static class Util
    {
        private static Random rnd = new Random();
        public static int GetRandom()
        {
            return rnd.Next();
        }
    }
}

So you can call:

var i = Util.GetRandom();

all throughout. If you strictly need a true stateless static method to generate random numbers, you can rely on a Guid.

public static class Util
{
    public static int GetRandom()
    {
        return Guid.NewGuid().GetHashCode();
    }
}

It's going to be a wee bit slower, but can be much more random than Random.Next, at least from my experience.

But not:

new Random(Guid.NewGuid().GetHashCode()).Next();

The unnecessary object creation is going to make it slower especially under a loop.

And never:

new Random().Next();

Not only its slower (inside a loop), it's randomness is... well not really good according to me..

cygnim
  • 1,985
  • 2
  • 16
  • 22
nawfal
  • 70,104
  • 56
  • 326
  • 368
  • 2
    Guid.GetHashCode does not guarantee any kind of randomness. It's a gamble to use it. I guess it's ok to wrap it in a whitening function such as `new Random`... – usr Oct 31 '15 at 18:28
  • @usr I know Guid.NewGuid is meant for uniqueness and not randomness but hash of it (Guid.GetHashCode) is pretty random. This is becasue Guid.GetHashCode is based on the string representation of the Guid. If you are saying hash code implementation of string is not documented and hence behaviour can't be guaranteed, I agree, but in practice it is pretty random, in the sense it lacks a predictable pattern. – nawfal Oct 31 '15 at 21:10
  • 1
    Your first example is not thread safe. Assuming you have more than one thread calling the static method, you'll have a problem. `.Next()` [is not thread-safe and could feasably throw an IndexOutOfRange exception under concurrent use](https://referencesource.microsoft.com/#mscorlib/system/random.cs,113). – Lilith River May 03 '17 at 20:17
5

From MSDN: Random Class (System):

"The random number generation starts from a seed value. If the same seed is used repeatedly, the same series of numbers is generated. One way to produce different sequences is to make the seed value time-dependent, thereby producing a different series with each new instance of Random. By default, the parameterless constructor of the Random class uses the system clock to generate its seed value, while its parameterized constructor can take an Int32 value based on the number of ticks in the current time. However, because the clock has finite resolution, using the parameterless constructor to create different Random objects in close succession creates random number generators that produce identical sequences of random numbers. The following example illustrates that two Random objects that are instantiated in close succession generate an identical series of random numbers..."

Wikipedia explains PRNGs

5

The best way to do it is to have a ThreadStatic Random instance:

[ThreadStatic] static Random random;

Random Get() {
 if (random == null) random = new Random(Guid.NewGuid().GetHashCode());
 return random;
}

This takes care of everything.

  1. Thread safety
  2. Performance
  3. No need to seed

It eludes me why the .NET Framework (and any other framework on earth) does not use something in this spirit.

usr
  • 168,620
  • 35
  • 240
  • 369
  • ThreadStatic (or ThreadLocal) themselves incur overhead so it doesn't take care of "everything". – user2864740 Sep 21 '16 at 03:14
  • 1
    This is true... but it's so much cheaper than creating a new Random instance each time. The delta between this and passing around a Random reference is quite low. CoreClr was recently changed to do what this answer says in order to have random seeds available for doing new Random(). @user2864740 – usr Sep 21 '16 at 09:31
  • (I'm using this approach which works well and is easy to reason about; just exposing my pedantic nature towards universals.) – user2864740 Sep 21 '16 at 18:14
  • 1
    I do not disagree with that behavior :) – usr Sep 21 '16 at 18:16
3

Why not?

You need to create an instance because the way random numbers are generated is that previous answers affect subsequent answers. By default, the new Random() constructor uses the current system time to "seed" the sequence, but it doesn't have to: you can pass your own number in if you like. In particular:

var rand = new Random(1234);
Console.WriteLine(rand.Next(0, 100));
Console.WriteLine(rand.Next(0, 100));
Console.WriteLine(rand.Next(0, 100));
Console.WriteLine(rand.Next(0, 100));

Will produce the same sequence of "random" number every time.

That means the Random class needs to keep instance data (the previous answer, or "seed") around for subsequent calls.

Dean Harding
  • 71,468
  • 13
  • 145
  • 180
3

Creating a new instance of Random then calling it immediately multiple times, e.g.:

for (int i = 0; i < 1000; i++)
{
     Random rand = new Random();
     Console.WriteLine(rand.Next(1,100));
}    

Will give you a distribution that is weighted towards the lower end of the range.

Doing it this way:

Random rand = new Random();
for (int i = 0; i < 1000; i++)
{
     Console.WriteLine(rand.Next(1,100));
}    

Will give you a better distribution.

Mathieu Borderé
  • 4,357
  • 2
  • 16
  • 24
cjk
  • 45,739
  • 9
  • 81
  • 112
1

Creating a short-lived instance in C# is almost free. Don't waste your time worrying about this. You probably have better places to look for perf or memory gains.

psychotik
  • 38,153
  • 34
  • 100
  • 135
1

Random number generators must maintain state in order to be "random." The random number generator creates a sequence that is generated based on a random seed. The problem is that nothing in a computer is actually random. The closest thing the computer has at hand is the system clock; that is the effectively the time at which the process takes place. So by default the current tick count of the system clock is used. If your application is fast enough then many random number calculations may occur under the same system tick. If the random number generator doesn't maintain state at all, it will provide the same random number multiple times (same input gives the same output). This is not usually what you want.

I know its already answered, but I just have to say that I prefer to use the singleton pattern in this case.

Jordan
  • 9,642
  • 10
  • 71
  • 141
-1

You need something similar to this if you want the syntax you mention.

namespace MyRandom
{
    public class Random
    {
        private static m_rand = new Random();
        public static Next(int min, int max)
        {
            return m_rand.Next(min, max);
        }
    }
}

This should allow you to do Random.Next(1,100); without having to worry about seeding.

LaustN
  • 722
  • 3
  • 7