1

我怎样才能得到一个IEnumerable随机值?我很失望Random类没有实现IEnumerable<int>

4

3 回答 3

8

编写一个将新值的扩展方法。yield return

public static IEnumerable<int> GetRandomValues(this Random instance)
{
    while(true)
    {
        yield return instance.Next();
    }
}
于 2012-07-11T14:49:34.980 回答
3

例如,您可以很容易地自己实现这一点

public IEnumerable<int> RandomInts(int below)
{
    Random r = new Random();
    while (true) yield return r.Next(below);
}
于 2012-07-11T14:50:43.593 回答
1

IEnumerable<int>有一个Random 类的实例的一些问题点是

  • 随机生成器有无限多的元素,因此在元素上使用foreach构造或循环将永远不会终止。
  • from应该返回的IEnumerator<int>实例具有将枚举数重置为集合开头的函数。假设行为正确,这应该返回第一个生成的随机数,因为它是在过去生成的。getEnumeratorIEnumerable<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
    }
}
于 2012-07-11T15:26:39.157 回答