Colonel Panic
Colonel Panic

Reputation: 137594

How do you create an enumeration of random values?

How can I get an IEnumerable of random values? I'm disappointed the class Random doesn't implement IEnumerable<int>.

Upvotes: 1

Views: 585

Answers (3)

Laar
Laar

Reputation: 614

The some problematic points off having an IEnumerable<int> instance for the Random class are

  • The random generator has infinitely many elements, therefore using the foreach construct or an loop over the elements will never terminate.
  • The IEnumerator<int> instance which getEnumerator from IEnumerable<int> should return has a function Reset which resets the enumerator to the begin of the collection. Assuming correct behaviour this should return the first generated random number, as it was generated in the past.

The last problem can be solved in at least two ways,

  • Keeping an list of already generated values, this might not be very memory efficient, but at least ensures that it will always return the same values after resetting.
  • Keeping the starting seed and when Reset is called a new generator can be instantiated with the previous seed. All other random generating methods of Random should be hidden to prevent the, from being accessed.

As the bookkeeping method is not very good, I would go for the second version. Which is quite a large class, as you can see below.

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
    }
}

Upvotes: 1

Rawling
Rawling

Reputation: 50114

You can implement this yourself fairly easily, for example

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

Upvotes: 3

Jakub Konecki
Jakub Konecki

Reputation: 46008

Write an extension method that will yield return new values.

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

Upvotes: 8

Related Questions