0

In order to ensure different random numbers, you should use just one instance of a Random class, as suggested in the answers here, here and here.

In my library, I need the random numbers, so I created a class Randomizer, which provides methods, that returns random numbers using single Random instance. Here is a fragment of the Randomizer code:

class Randomizer
{
    private Randomizer() { }
    public static Randomizer Instance { get; } = new Randomizer();

    private static readonly Random random = new Random();
    private static readonly object syncLock = new object();

    public int Next(int minValue, int maxValue)
    {
        lock(syncLock)
        {
            return random.Next(minValue, maxValue);
        }
    }

    // rest of code
}

Now, what if a user of my library also need the random numbers? Should I make my Randomizer class public and specify in the documentation of the library, that users should use my Randomizer class in order to generate random numbers?

Community
  • 1
  • 1
Dariusz
  • 610
  • 1
  • 6
  • 14
  • 3
    You should at least provide a constructor that takes a `Random` instance – Tim Schmelter Aug 23 '16 at 10:59
  • 1
    What will the random number be used for? – Jonathan Aug 23 '16 at 11:09
  • If I provide a constructor that takes a `Random` instance, I will have to create a `Random` instance somewhere else inside my library. Then should I create somewhere public (out of library) property or method, which returns this instance? Or should user of the library create `Random` instance and pass it to the `Randomizer` constructor **before** any of the other library class will be used? @Matt I know it, but in the `Random.Next(int, int)` method, the second argument is also called maxValue @Jonathan I will use them, to check, if random number is less than some specified value. – Dariusz Aug 23 '16 at 11:20
  • @TimSchmelter If you are going to do that, then simply let the consumer use his own `Random`; you are alreading burdening him with creating his own instance, why burden him also with using a wrapper class that doesn't really add any value? – InBetween Aug 23 '16 at 11:22
  • @InBetween: i'm not burdening him with it, i'm enable him to use his own `Random` instance if needed, for example to enfore always the same "random" number sequence(unit tests etc.). Of course he's free to use the default constructor. – Tim Schmelter Aug 23 '16 at 11:26
  • @Jonathan These random numbers will only be used internally within library. – Dariusz Aug 23 '16 at 11:26
  • @TimSchmelter Then he'd directly use his own `Random`, not wrap it in a class that doesn't add anything and it most definitely doesn´t enforce a singleton generator; nothing would prevent you from calling the constructor again with a new `Random` instance that would reset the wrapper class and would mess up the inner working of the library. I find the constructor pointless and potentially harmful to the inner workings of the library, to be honest. – InBetween Aug 23 '16 at 11:35
  • Possibly this is overkill. If you can keep it simple and for example not instantiate new instances of Random then do that instead. – Jonathan Aug 23 '16 at 11:37

4 Answers4

2

In order to ensure different random numbers, you should use just one instance of a Random class

That's not quite right. It's perfectly fine to create multiple instances of Random as long as you don't initialise them all in a tight loop (since they are seeded by the current time, so you want the current time to be different for each at the point of instantiation).

As you're creating a static class that just creates one Random object and reuses it, that's fine. It's theoretically possible that a caller of your library could create their own static Random that gets created at the same time, so their generator gets the same seed as yours and so the same sequence of random numbers. That probably won't happen because of the time it takes to create the static classes. It also probably won't matter anyway unless there's a reason why correlation matters between the caller's sequence and yours.

Matthew Strawbridge
  • 19,940
  • 10
  • 72
  • 93
0

Why are you burdening the consumer of your library with your own implementation?

If its internal its because you need a very specific random provider for the inner workings of your library. If there is no need that an external consumer also abides to the rules you've imposed in your code when interacting with your library then don't expose your generator and let the user use his own Random if he needs to.

On the other hand, if you need the consumer to use your specific random generator when interacting with the public API of your library, then you would need to publicly expose the class.

InBetween
  • 32,319
  • 3
  • 50
  • 90
  • There is no need to let conumer use my specific random generator. But if consumer create his own `Random` instance, will numbers generated by two `Random` instance (my, inside library and consumer's) be really random? I have read, that I should use just one `Random` instance (see links in the question). – Dariusz Aug 23 '16 at 11:33
  • 1
    @Darko. No, there is absolutely no issue. See [Matthew Strawbridge](http://stackoverflow.com/users/241605/matthew-strawbridge) [answer](http://stackoverflow.com/a/39100001/767890), where he explains what potential issues arise when creating multiple `Random` instances. – InBetween Aug 23 '16 at 11:40
0

Initialize your Random object by using an explicit seed that is guaranteed to be random (e. g. get one from the operating system). That way it doesn't matter whether the user creates his own instances of Random and you don't need to think about synchronizing calls to the Next method with user code.

However if your are unable to get a random seed, one solution would be to define an interface and let users of your library to inject an instance to each component that needs random numbers:

public interface IRandomizer
{
    int Next(int minValue, int maxValue);
}

The contract of this interface must define the exact needs of your library (e. g. that the Next method has to be thread-safe). Your Randomizer class may implement this interface to be used as the default implementation.

For example an key generator library component may provide two constructors:

public class KeyGenerator
{
    private IRandomizer randomizer;

    public KeyGenerator(IRandomizer randomizer) 
    {
        // instance will use the specified IRandomizer
        this.randomizer = randomizer;
    }

    public KeyGenerator()
    {
        // instance will use your Randomizer class.
        this.randomizer = Randomizer.Instance;
    }
}

This way the user of your library can decide whether he wants to provide his own random number generator or use the default of your library.

muton
  • 382
  • 2
  • 9
0

I'd use the following approach:

public interface IRandomizer
{
    int Next(int inclusiveLower, int exclusiveOuter);
}

And then I'd expose a static class with a default implementation and optionally a factory method to create specific "seeded" instances. Note that the internally used generator (Default) is publicly accesible but it could perfectly well be internal only:

//Note, the following code is an outline of the general idea

public static class RandomGenerator
{
    private readonly static Lazy<Randomizer> inner = new Lazy<Randomizer>();
    public static IRandomizer Default { get { return inner.Value; } }

    public static IRandomizer CreateNew(Random seed)
    {
        return new Randomizer(seed);
    }

    private class Randomizer : IRandomizer
    {
        private readonly Random random;
        private readonly object syncLock = new object();

        public Randomizer(Random seed = null)
        {
            random = seed ?? new Random();
        }

        public int Next(int minValue, int maxValue)
        {
            lock (syncLock)
            {
                return random.Next(minValue, maxValue);
            }
        }
    }
}
InBetween
  • 32,319
  • 3
  • 50
  • 90