2012-07-11 73 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 
    } 
} 
相关问题