2012-01-27 43 views
3

我試圖從隨機類中擴展函數。如何將函數擴展爲隨機類

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的Suposse ...它有可能比其他類應該刷新或更新新的種子?我知道這是行不通的。也許我需要一個靜態屬性,我不確定。

+0

你可以發表說明所需行爲的代碼嗎? – Restuta 2012-01-27 06:36:12

回答

4

您需要使用Singleton模式(參見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; 
     } 
    } 
} 

然後,您可以訪問隨機的同一個實例代碼中的任何位置如下:

RandomSingleton.Instance.NextInt(24); 

請注意,這個Random實例不需要重新播種,因爲所有代碼都將使用相同的實例,因此您將看不到重複的數字。

+1

爲什麼不使用簡單的靜態隨機實例(如果線程安全不是問題)? – 2012-01-27 06:43:03

+0

好點。你可以。儘管由此模式給出了延遲初始化 - 對於它的價值 – ColinE 2012-01-27 06:44:51

+0

考慮使用'private static Lazy instance;' 而不是'私人靜態隨機實例;' 它將是線程安全的,並且在getter代碼中不需要'if ..',只需'return instance.Value'。 HTH .. – ShloEmi 2015-04-08 04:56:23

4

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這裏防止這一切會不可預知時正在使用的多個線程;儘管在那一點上你不能保證可重複的訂單反正,但至少它不會在火花中爆炸。