开发者

Correct method of a "static" Random.Next in C#?

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 Rando开发者_Python百科m class to do the same? like...

Random.Next(1,100);

I don't want to create an instance unnecessarily


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.


//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


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);


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..


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


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.


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.


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.


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.


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.


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜