How to Seed a Random Class in C#

  1. Create a Function to Seed a Random Class in C#
  2. Use the Random() Class to Seed a Random Class in C#
  3. Use the Environment.TickCount Property to Seed a Random Class in C#
  4. Use the RNGCryptoServiceProvider Class to Seed a Random Class in C#
How to Seed a Random Class in C#

This tutorial will discuss how to seed a class in C# to achieve randomness in your applications. There are four primary ways to seed a class, and it all starts with the Random class allows you to generate numbers without a specific range by initializing its instance and calling the Next() method to get a random integer and can get a decimal by using the NextDouble() method.

You can write a class from scratch. You can use the Random class, the Environment.TickCount, or the RNGCryptoServerProvider class to seed a random class in C#.

Create a Function to Seed a Random Class in C#

Create a function like public static int random_func(int _min, int _max){} and create an object from the Random class to perform the Next() method on the min and max values.

You can reiterate this technique by creating a static class that holds the public function performing operations on a private static object from the Random class. For a true stateless static method, you can strictly rely on a Guid to generate random numbers with something like Guid.NewGuid().GetHashCode().

using System;
using System.Windows.Forms;

namespace seed_random_class {
  public partial class Form1 : Form {
    // function to get a random number
    public static int RandomNumber(int min, int max) {
      Random random = new Random();
      return random.Next(min, max);
    }
    public Form1() {
      InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e) {}

    private void label1_Click(object sender, EventArgs e) {}

    private void button1_Click(object sender, EventArgs e) {
      int min = 0;
      int max = 10;
      int return_num;
      return_num = Form1.RandomNumber(min, max);
      label1.Text = return_num.ToString();

      /* alternative approach

      byte[] _random = new byte[6];
      for (int i = 0; i < 6; ++i)
      _random[i] = (byte)(Form1.RandomNumber((int)0xFFFF, (int)0xFFFFFF) % 256);

      */
    }
  }
}

Output:

Create a Function to Seed a Random Class

It’s important to understand that Guid aim is to be unique not uniformly distributed and can be in most cases the opposite of randomness and does not implement a uniform distribution and that’s why creating a function based on the Random class is a valid approach. You will also get better randomness by seeding a random class with a larger unpredictable number like Random((int)DateTime.Now.Ticks).

Use the Random() Class to Seed a Random Class in C#

Creating an instance of the Random class and applying the Next() method on that instance in a loop is always the best way to seed the classes in C#. The numbers a single Random class instance generates are always uniformly distributed, and you can seed them with identical values to generate identical random numbers by creating a new Random class instance for every random number in quick succession.

It’s a great practice to re-seed a Random class for the sake of completeness and create a new instance from the new seed and re-seeding is a great option when predictability becomes an issue, and apart from using a truer random generator, you should re-seed faster than pattern recognition can apply from an attacker side and can ensure no two generators are seeded with the same values.

The new Random() is always initialized using the system clock means that you can get the same values. Hence you should keep a single Random instance and keep using the Next() method on the same instance.

using System;
using System.Windows.Forms;

namespace seed_random_class {
  public partial class Form1 : Form {
    public Form1() {
      InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e) {}

    private void label1_Click(object sender, EventArgs e) {}

    private void button1_Click(object sender, EventArgs e) {
      var _random = new Random();
      for (int i = 0; i < 100; ++i) label1.Text = _random.Next(1, 100).ToString();
    }
  }
}

Output:

Use the Random() Class to Seed a Random Class

Most importantly, you need a lock to synchronize the seed with the Next() because if you apply Next() at the same time to multiple threads, you can make the outcome even more random, and doing so can potentially break the internal implementation. The lock guarantees thread safety, and synchronizing is the best approach to achieve maximum randomness.

Using lock with a Random class instance is an alternative but less thread-safe than the other. Suppose you are using thread and parameterless constructor of the Random object.

In that case, it can face a delay caused by calling the Thread.Sleep method leads to producing a different seed value for that object and can generate a different sequence of random numbers.

Use the Environment.TickCount Property to Seed a Random Class in C#

It belongs to the System namespace and holds importance to getting the number of milliseconds since the system started and represents a 32-bit signed integer. This property cycles between Int32.MinValue and Int32.MaxValue respectively representing negative and positive numbers, and you can remove the sign bit to yield a non-negative number that cycles between zero and maximum positive value once every 24.9 days.

The resolution of its 32-bit signed integer is limited to the resolution of your system timer ranges from 10 to 16 milliseconds. Most importantly, the implementation used by System.Random is Environment.TickCount and avoids having to cast DateTime.UtcNow.Ticks and can ease the re-use of seeding the random classes throughout your C# application.

using System;
using System.Threading;  // essential namespace for threading
using System.Windows.Forms;

namespace seed_random_class {
  public static class StaticRandom {
    // initialize the seed
    private static int _var_seed;

    // a thread-safe approach to access the random class via seed
    // `<Random>` implies the Random class
    private static ThreadLocal<Random> local_thread =
        new ThreadLocal<Random>(() => new Random(Interlocked.Increment(ref _var_seed)));

    // method that utilizes the `Environment.TickCount` property
    static StaticRandom() {
      _var_seed = Environment.TickCount;
    }

    public static Random class_inst {
      get { return local_thread.Value; }
    }
  }
  public partial class Form1 : Form {
    public Form1() {
      InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e) {}

    private void label1_Click(object sender, EventArgs e) {}

    private void button1_Click(object sender, EventArgs e) {
      label1.Text = StaticRandom.class_inst.Next(1, 100).ToString();
    }
  }
}

Output:

Use the Environment.TickCount Property to Seed a Random Class

Use the RNGCryptoServiceProvider Class to Seed a Random Class in C#

In some unique cases, using the RNGCryptoServerProver class becomes necessary. It belongs to the System.Security.Cryptography namespace and implements a cryptographic RNG (Random Number Generator) using the implementation provided by the CSP (Cryptographic Service Provider) and cannot be inherited.

It is important to dispose of it either directly or indirectly because it implements the IDisposable interface, and you can call the Dispose method in a try/catch block. In C#, you can use the using construct to dispose of it to create a perfect seed for your random class.

The System.Security.Cryptography.RNGCryptoServiceProvider class is thread-safe do serve a genuine need by reproducing values from a known seed. However, it is mathematically impossible to create a function that can generate two independent values, and this also implies any cryptographic scheme is not completely safe, and sometimes the sheer cost of using it can be too much.

using System;
using System.Windows.Forms;

namespace seed_random_class {
  public partial class Form1 : Form {
    public Form1() {
      InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e) {}

    private void label1_Click(object sender, EventArgs e) {}

    private void button1_Click(object sender, EventArgs e) {
      byte[] foo = { 0x32, 0x00, 0x1E, 0x00 };
      System.Security.Cryptography.RNGCryptoServiceProvider prov =
          new System.Security.Cryptography.RNGCryptoServiceProvider();
      prov.GetBytes(foo);
    }
  }
}

Output:

Use the RNGCryptoServiceProvider Class to Seed a Random Class

You can use the Next(int) or Next(int min, int max) methods to generate random numbers in range or can use the Next() and NextBytes() to generate respectively random integers and series of byte values. Either you supply a seed through the constructor overload, or the framework will take care of this for you.

It is an expensive approach to instantiate the Random class and overdoing it can decrease the performance of your C# applications; instead, instantiate a single Random instance and call the Next() method multiple times. Cryptography is a more secure and protective approach to seed a random class in C#.

Syed Hassan Sabeeh Kazmi avatar Syed Hassan Sabeeh Kazmi avatar

Hassan is a Software Engineer with a well-developed set of programming skills. He uses his knowledge and writing capabilities to produce interesting-to-read technical articles.

GitHub

Related Article - Csharp Math