【问题标题】:How to extend functions to Random class如何将函数扩展到 Random 类
【发布时间】:2012-01-27 06:26:18
【问题描述】:

我正在尝试从 Random 类扩展函数。

public static class RandomExtensions
{
    public static void NextEven(this Random rnd, int min, int max)
    {
        // ...
    }

    public static void ReseedRandomNumberGenerator(this Random rnd, int? seed = null)
    {
        rnd = seed.HasValue ? new Random(seed.Value) : new Random(); 
    }
}

但我怀疑的是第二个函数ReseedRandomNumberGenerator。我需要许多类可以与 Random 类交互的东西,但所有这些类都应该具有相同的实例。

假设我调用 ReseedRandom... 有可能比其他类刷新或更新新种子?

public class A()
{
        protected Random Random = new Random();
}

public class B()
{
        protected Random Random = new Random();
}

我知道这行不通。也许我需要一个静态属性,我不确定。

【问题讨论】:

  • 您能发布说明所需行为的代码吗?

标签: c# random static extension-methods random-seed


【解决方案1】:

this 参数是 by-val,意思是:调用者不会注意到您对该值所做的任何重新分配,因此您的 Reseed... 方法不会做任何调用者会注意到的事情。要做到这一点,听起来你想要一个静态实例,但你也需要注意线程安全等问题。

就我个人而言,我会创建一个单独的 API,例如:

public static class MyRandom {
    static Random random = new Random();
    static readonly object sync = new object();
    public static void Seed(int seed) {
        lock(sync) { random = new Random(seed); }
    }
    public static int Next() {
        lock(sync) { return random.Next(); }
    }
    public static int Next(int max) {
        lock(sync) { return random.Next(max); }
    } 
    ...
}

这里使用lock 可以防止在被多个线程使用时这一切都变得不可预测;虽然在那个时候你不能保证一个可重复的订单无论如何,但至少它不会在火花中爆炸。

【讨论】:

    【解决方案2】:

    您需要使用单例模式(参见 MSDN 上的Implementing Singleton in C#

    public class RandomSingleton
    {
       private static Random instance;
    
       private RandomSingleton() {}
    
       public static Random Instance
       {
          get 
          {
             if (instance == null)
             {
                instance = new Randon();
             }
             return instance;
          }
       }
    }
    

    然后,您可以在代码中的任何位置访问相同的 Random 实例,如下所示:

    RandomSingleton.Instance.NextInt(24);
    

    请注意,无需重新播种此 Random 实例,因为您的所有代码都将使用同一个实例,因此您不会看到重复的数字。

    【讨论】:

    • 为什么不使用简单的静态随机实例(如果线程安全不是问题)?
    • 好点。你可以。尽管因此模式提供了延迟初始化 - 值得
    • 考虑使用'private static Lazy instance;'而不是“私有静态随机实例;”这将是线程安全的,并且您不需要 getter 代码中的“if..”,只需“return instance.Value”。 HTH..
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-30
    • 1970-01-01
    • 1970-01-01
    • 2014-12-08
    相关资源
    最近更新 更多