2012-07-11 70 views
0

如何獲得隨機值IEnumerable?我對班級Random未執行IEnumerable<int>感到失望。你如何創建一個隨機值的枚舉?

+0

會隨機產生一組號碼,並將其存儲在一個列表,其中實現IEnumerable ,滿足您的要求嗎? – 2012-07-11 14:50:52

+1

而我很失望,它沒有實現'IEnumerable '......哦,現在我明白他們爲什麼沒有實現。 – user7116 2012-07-11 14:53:40

回答

8

編寫一個擴展方法即將yield return新值。

public static IEnumerable<int> GetRandomValues(this Random instance) 
{ 
    while(true) 
    { 
     yield return instance.Next(); 
    } 
} 
+2

+1喜歡隨機擴展的想法 – 2012-07-11 14:53:15

+0

謝謝。如果我創建了一個'GetEnumerator'擴展方法,我現在能夠在類型爲Random的對象上進行「foreach」操作嗎? – 2012-07-11 15:00:19

+0

+1這是一個比我匆忙編寫的答案更好的API。 – 2012-07-11 15:01:36

3

你可以很容易自己實現,例如

public IEnumerable<int> RandomInts(int below) 
{ 
    Random r = new Random(); 
    while (true) yield return r.Next(below); 
} 
+0

+1不錯和簡單! – n8wrl 2012-07-11 14:52:18

+2

我會通過隨機的實例來避免播種問題。 – CodesInChaos 2012-07-11 14:55:00

+0

@代碼是的,這是一個好主意......但是,我的答案與Jakub的答案几乎相同:p – Rawling 2012-07-11 15:13:27

1

的一些問題點過具有Random類的IEnumerable<int>實例是

  • ,隨機數生成有無窮多元素,因此使用foreach構造或元素上的循環將永遠不會終止。
  • IEnumerator<int>getEnumeratorgetEnumeratorIEnumerable<int>應該返回的函數Reset將枚舉數重置爲集合的開始。假設正確的行爲,這應該返回第一個生成的隨機數,因爲它是在過去生成的。

最後一個問題可以以至少兩種方式來解決,

  • 保持已經產生的值的列表,這可能不是非常高效存儲,但至少保證了它總是會返回重置後的值相同。
  • 保留起始種子,並且當Reset被稱爲新的生成器時可以用前一個種子實例化。 Random的所有其他隨機生成方法應被隱藏以防止被訪問。

由於簿記方法不是很好,我會去第二個版本。這是一個相當大的階級,你可以看到下面。

public class RandomInt : IEnumerable<int> 
{ 
    int seed; 

    public RandomInt() 
    { 
     seed = new Random().Next(); 
    } 


    public IEnumerator<int> GetEnumerator() 
    { 
     return new InternalEnumerator (seed); 
    } 

    protected class InternalEnumerator : IEnumerator<int> 
    { 
     Random randomGen; 
     int current; 
     int seed; 

     protected InternalEnumerator (int seed) 
     { 
      this.seed = seed; 
     } 

     #region IEnumerator implementation 
     public bool MoveNext() 
     { 
      if (randomGen == null) 
       randomGen = new Random (seed); 
      current = randomGen.Next(); 
      return true; 
     } 

     public void Reset() 
     { 
      randomGen = null; 
     } 

     public int Current { 
      get { 
       if (randomGen == null) 
        throw new InvalidOperationException ("Enumerator in reset state"); 
       return current; 
      } 
     } 
     #endregion 
    } 
} 
相關問題