Random Extensions for C#

Today I thought I’d discuss some extensions I use to the .NET Random object. Previously, I had these functions is a separate wrapper class but I found that moving them to a static extension class would be a better fit across my projects.

To start with, let’s take a look at what Extension methods are. Extension methods in C# allow you “roll your own” methods into existing types without having to create a new derived type. Extension methods are placed in a static class, but, by using a special syntax, they are called as if though they belonged to the original type. In your C# code calling an extension method looks the same as calling a method defined by the base type.

So, let’s take a look at how your would define a class that held Extension methods. Here’s how I’m starting out my Random Extensions class.

public static class RandomExtensions
{

You don’t have to define the whole class as static. You can define it normally if you want. I’ve just found it better myself to treat these classes just like I would static function classes I’ve done before. I also create a separate class for each method I’m extending instead of doing a ‘grab bag’ of unrelated functions. This helps keep things better organized, something that’s quite important when using extension methods.

Now let’s look at some of my functions.

One thing I like to do is to reseed the randomization on each call. There is, of course, some overhead in doing this but I find the improved level of random results to be worth it. To do this, I create a function called Increment that pushes the random counter a variable distance using the Next method and the current time in milliseconds and seconds. Here’s the function…

public static void Increment(this Random rand)
{
    int value = DateTime.Now.Millisecond + DateTime.Now.Second;
    for (int Counter = 0; Counter <= value; Counter++)
    {
        rand.Next();
    }
}

Notice how the extension method is defined with the ‘this’ followed by the type name and then variable name. This is what tells the .Net framework that this is an extension of the Random type.

One of my long running gripes about the .NET Random type is with the range overload built into the Next method, specifically that the maximum value isn’t inclusive. Therefore, if you do RandomInstance.Next(1,6), like you would to simulate a dice, you would only get values back from 1 to 5. Instead, you would need to use (1,7) to get values from 1 to 6 back. It’s too late for Microsoft to change this behavior since it would break too much existing code. But, if you want, you can use extension methods to change it for you in your code while leaving the default behavior intact. I did my own function that included the given max value in the range. Here’s the function…

public static int Range(this Random rand,int low, int high)
{
    rand.Increment();
    return rand.Next(low, high + 1);
}

Here you’ll see I increment the random value prior to the value between retrieved via the Next method. This gives an extra touch of randomization.

Another useful function I’ve needed from time to time is a way to build a random sequence of integers I can use to access data randomly. For example, if I wanted to select 10 random records from a database table that had an integer primary key, this function would help me to grab a random selection of records. Another use, which I’ll show below, is to help in scrambling the contents of a list.

To create the random sequence, I’m using a Queue generic type. This allows me to automatically remove used number from the list and thus makes it easier to manage. Here’s the function…

public static Queue SequenceQueue(this Random rand, int max)
{
    Queue ReturnValue = new Queue();
    while (ReturnValue.Count <= max)
    {
        int Result = rand.Range(0, max);
        if (!ReturnValue.Contains(Result))
        {
            ReturnValue.Enqueue(Result);
        }
    }
    return ReturnValue;
}

As you can see, I use my Range method to load in values to the Queue.

I also have a related method called Sequence that returns a generic List instance rather than a Queue. This is useful when you want to use a random sequence in a LINQ query. Here’s an example of this technique working with a LINQ-to-SQL datasource…

Random Rnd = new Random();
TestDataContext TestData = new TestDataContext();
int MaxTest = (from items in TestData.TestItems select items.ID).Max();
List RandomIDs = Rnd.Sequence(1,MaxTest,10);
List ItemList = (from item in
                 TestData.TestItems.Where(item => RandomIDs.Contains(item.ID))
                 select item).ToList();

My last Random extension method, Scramble, scrambles up the contents of a generic list. One place a routine like this could be used is in a card game, where the members of the original list were the card objects.

public static List Scramble(this Random rand,List inputList) where T : IComparable
{
    List ReturnList = new List();
    Queue RandomQueue = rand.SequenceQueue(inputList.Count-1);
    while (RandomQueue.Count != 0)
    {
        ReturnList.Add(inputList[RandomQueue.Dequeue()]);
    }
    return ReturnList;
}

You can download my full RandomExtensions class here. In addition to the methods shown above, it also contains some additional overloads that I’ve found useful.

That wraps up this example of an extension to the Random type. Let me know if you see any problems with it or if you have any questions or thoughts about it by leaving a comment below.

Posted by Frank in C# Code Examples
Tags: ,, , , , , ,

Theme Provided By Free HTML Layouts