C#: Extension Method – Get a Random Element from a Collection


In my previous post I created a class to generate random text. Throughout the code I had to get a random element from various arrays of characters and integers. The class was riddled with the repeated code that generated a random number, from 0 to the length of the array minus one, which was then used to index into the array and select an element. Something like this:

int numberOfWords = possibleSentanceLengths[RandomNumber(0, possibleSentanceLengths.Length)];

I got to thinking and figured this was the perfect situation to use an extension method so that I could just call a GetRandomElement on any array of elements. Here is the method I came up with:

public static class Extensions
{
    private static Random random = new Random();
    
    public static T GetRandomElement<T>(this IEnumerable<T> list)
    {
        // If there are no elements in the collection, return the default value of T
        if (list.Count() == 0)
            return default(T);

        return list.ElementAt(random.Next(list.Count()));
    }
}

Note that the instance of the Random class is created outside the method GetRandomElement. If we were to create a new Random object each time the method was called and we were to call the method in a loop, the element returned would be the same every time as the Random class is seeded using the current time. Having the class created outside the scope of the method ensures a true psuedorandom number on each call to the Next method.

This nice thing about this extension method is that it is generic so it can be called on any collection that implements the IEnumerable interface including arrays, Lists, HashSets, Dictionaries, you name it. Here is the original code using our new extension method.

int numberOfWords = possibleSentanceLengths.GetRandomElement<int>();

I was bored with using the .NET provided Random class and tried to think of other ways that a random number could be generated. My first thought was to use a Guid as those are completely unique (up to a point as there are only so many possible 32 character Guids that can be generated). Creating a new Guid, generating its hash code and then using the mod operator allows us to index into the collection at a random location.

public static class Extensions
{  
    public static T GetRandomElement<T>(this IEnumerable<T> list)
    {
        // If there are no elements in the collection, return the default value of T
        if (list.Count() == 0)
            return default(T);

        // Guids as well as the hash code for a guid will be unique and thus random        
        int hashCode = Math.Abs(Guid.NewGuid().GetHashCode());
        return list.ElementAt(hashCode % list.Count());
    }
}

Any other ideas on how to generate a random number other than the two mentioned?

Advertisements