-1

In my class there are several methods with the following signature:

public static void SomeMethod()
{
 ...
}

Most of these methods depend on the value of the private static field. It is necessary that the caller had any way to assign a value to this field before calling any of these static methods.

I want to have a single Random object for use by all classes in the application. How do I pass a reference to this object to use it in the static methods of another class? I have a private static field in the class with static methods and a static initializer:

public static void Init(Random random)
{
  _random = random;
}

But how to make sure that the initializer was called? To do the check and throw exceptions in every method, it seems to me redundant. There may be another option.

Finally I found an acceptable solution for me:

  1. Define public static property in the class that contains application entry point:public static Random Rnd { get; } = new Random();

  2. Define private static Random _random in other classes;

  3. Implement a static constructor for other classes that includes this code:

        Type type = Assembly.GetExecutingAssembly().EntryPoint.DeclaringType;
        var randomTypeProperties =
            type.GetProperties().Where(p => p.PropertyType == typeof(Random));
        foreach (var propertyInfo in randomTypeProperties)
        {
            _random = (Random)propertyInfo.GetValue(null);
        }
    

I can mark a message from @Andy as the answer, because it is after all a static constructor.

Thank you to everyone who took part in the discussion.


It's never too late to learn. Yesterday, as I read about the design patterns, I realized that the Singlton is exactly what I needed:

public sealed class RandomAsSingleton : Random
{
    private static volatile RandomAsSingleton _instance;
    private static readonly object _syncRoot = new object();

    private RandomAsSingleton() { }

    public static RandomAsSingleton Instance
    {
        get
        {
            lock (_syncRoot)
            {
                if (ReferenceEquals(_instance, null)) { _instance = new RandomAsSingleton(); }
                return _instance;
            }
        }
    }
}

My previous solution seems to me a little bit ugly right now.

  • I think my question has a difference: a static constructor has no parameters. – retrograde.su Nov 18 '17 at 12:11
  • 1
    It sounds to me like you should reconsider the design. Make them *instance* methods, and expose only a constructor that accepts an initial value for the field. Then create a single instance of the object, and make that available (e.g. with DI) everywhere that it's needed. – Jon Skeet Nov 18 '17 at 12:44
  • Finally I found an acceptable solution for me: 1. Define public static property in the class that contains application entry point: public static Random Rnd { get; } = new Random(); 2. Define private static Random _random in other classes; – retrograde.su Nov 18 '17 at 15:19
  • I thought the point was that you couldn't initialize the static variable in a static constructor? You're effectively doing that, just in a roundabout way. It's very unclear why you can't just use a static constructor here. (It's not like you're able to specify a custom `Random` with your suggested approach.) – Jon Skeet Nov 18 '17 at 15:20
  • 3. Implement a static constructor for other classes that includes this code: Type type = Assembly.GetExecutingAssembly ().EntryPoint.DeclaringType; var randomTypeProperties = type.GetProperties().Where(p => p.PropertyType == typeof(Random)); foreach (var propertyInfo in randomTypeProperties) { _random = (Random)propertyInfo.GetValue(null); } – retrograde.su Nov 18 '17 at 15:21
  • Your question doesn't mention the entry point of the assembly at all. If that was part of the requirements, how on earth could you expect anyone to answer? You really need to work on making your questions clearer. See https://codeblog.jonskeet.uk/2010/08/29/writing-the-perfect-question/ – Jon Skeet Nov 18 '17 at 15:22

1 Answers1

0

You might want to use a static constructor

// Static constructor is called at most one time, before any
// instance constructor is invoked or member is accessed.
static SimpleClass()
{
    // set your private static field
}

https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/static-constructors

Andy
  • 3,997
  • 2
  • 19
  • 39
  • I know about static constructor. But in my case the value of a static field depends on external code. – retrograde.su Nov 18 '17 at 12:07
  • 1
    then that's not static, show us example. your question is too broad and so its duplicate. if you think your question is different elaborate more to show differences. be more specific. @retrograde.su – M.kazem Akhgary Nov 18 '17 at 12:14
  • In more detail, I want to have a single Random object for use by all classes in the application. How do I pass a reference to this object to use it in the static methods of another class? – retrograde.su Nov 18 '17 at 12:22
  • I have a private static field in the class with static methods and a static initializer: public static void Init(Random random) { _random = random; }. But how to make sure that the initializer was called? To do the check and throw exceptions in every method, it seems to me redundant. There may be another option. – retrograde.su Nov 18 '17 at 12:33