How do I select a random value from an enumeration?

C#RandomEnums

C# Problem Overview


Given an arbitrary enumeration in C#, how do I select a random value?

(I did not find this very basic question on SO. I'll post my answer in a minute as reference for anyone, but please feel free to post your own answer.)

C# Solutions


Solution 1 - C#

Array values = Enum.GetValues(typeof(Bar));
Random random = new Random();
Bar randomBar = (Bar)values.GetValue(random.Next(values.Length));

Solution 2 - C#

Use Enum.GetValues to retrieve an array of all values. Then select a random array item.

static Random _R = new Random ();
static T RandomEnumValue<T> ()
{
	var v = Enum.GetValues (typeof (T));
	return (T) v.GetValue (_R.Next(v.Length));
}

Test:

for (int i = 0; i < 10; i++) {
	var value = RandomEnumValue<System.DayOfWeek> ();
	Console.WriteLine (value.ToString ());
}

->

Tuesday
Saturday
Wednesday
Monday
Friday
Saturday
Saturday
Saturday
Friday
Wednesday

Solution 3 - C#

Here's an alternative version as an Extension Method using LINQ.

using System;
using System.Linq;

public static class EnumExtensions
{
	public static Enum GetRandomEnumValue(this Type t)
	{
		return Enum.GetValues(t)          // get values from Type provided
			.OfType<Enum>()               // casts to Enum
			.OrderBy(e => Guid.NewGuid()) // mess with order of results
			.FirstOrDefault();            // take first item in result
	}
}
					
public static class Program
{
	public enum SomeEnum
	{
		One = 1,
		Two = 2,
		Three = 3,
		Four = 4
	}
	
	public static void Main()
	{
		for(int i=0; i < 10; i++)
		{
			Console.WriteLine(typeof(SomeEnum).GetRandomEnumValue());
		}
	}			
}

> Two
> One
> Four
> Four
> Four
> Three
> Two
> Four
> One
> Three

Solution 4 - C#

You could just do this:

var rnd = new Random();
return (MyEnum) rnd.Next(Enum.GetNames(typeof(MyEnum)).Length);

No need to store arrays

Solution 5 - C#

Call Enum.GetValues; this returns an array that represents all possible values for your enum. Pick a random item from this array. Cast that item back to the original enum type.

Solution 6 - C#

Adapted as a Random class extension:

public static class RandomExtensions
{   
    public static T NextEnum<T>(this Random random)
    {
        var values = Enum.GetValues(typeof(T));
        return (T)values.GetValue(random.Next(values.Length));
    }
}

Example of usage:

var random = new Random();
var myEnumRandom = random.NextEnum<MyEnum>();

Solution 7 - C#

Here is a generic function for it. Keep the RNG creation outside the high frequency code.

public static Random RNG = new Random();

public static T RandomEnum<T>()
{  
	Type type = typeof(T);
	Array values = Enum.GetValues(type);
    lock(RNG)
    {
	    object value= values.GetValue(RNG.Next(values.Length));
	    return (T)Convert.ChangeType(value, type);
    }
}

Usage example:

System.Windows.Forms.Keys randomKey = RandomEnum<System.Windows.Forms.Keys>();

Solution 8 - C#

A lot of these answers are pretty old and - correct me if I'm wrong - seem to work with some sketchy concepts like type erasure and dynamic type casting. However, as user Yarek T points out, there's no need for that with the generic overload of Enum.GetValues:

static Random random = new Random();

// Somewhat unintuitively, we need to constrain the type parameter to
// both struct *and* Enum - struct is required b/c the type can't be
// nullable, and Enum is required b/c GetValues expects an Enum type.
// You'd think that Enum itself would satisfy the non-nullable
// constraint, but alas, me compiler tells me otherwise - perhaps
// someone more knowledgeable can explain why this is in a comment?
static TEnum RandomEnumValue<TEnum>() where TEnum : struct, Enum
{
    TEnum[] vals = Enum.GetValues<TEnum>();
    return vals[random.Next(vals.Length)];
}

Or, like in borja garcia's answer, we can even write this as an extension of the random class

public static class RandomExtensions
{   
    public static TEnum NextEnumValue<TEnum>(this Random random)
        where TEnum : struct, Enum
    {
        TEnum[] vals = Enum.GetValues<TEnum>();
        return vals[random.Next(vals.Length)];
    }
}

And we can run the same test from mafu's answer:

Random random = new Random();
for (int i = 0; i < 10; i++) {
    var day = random.NextEnumValue<System.DayOfWeek>();
    Console.WriteLine(day.ToString());
}

Potential output:

Thursday
Saturday
Sunday
Sunday
Sunday
Saturday
Wednesday
Monday
Wednesday
Thursday

Solution 9 - C#

The modern answer combining this answer and its comment:

public static class RandomExtensions
{
    private static Random Random = new Random();

    public static T GetRandom<T>() where T : struct, Enum
    {
        T[]? v = Enum.GetValues<T>();
        return (T)v.GetValue(Random.Next(v.Length));
    }
}

Solution 10 - C#

Personally, I'm a fan of extension methods, so I would use something like this (while not really an extension, it looks similar):

public enum Options {
    Zero,
    One,
    Two,
    Three,
    Four,
    Five
}

public static class RandomEnum {
    private static Random _Random = new Random(Environment.TickCount);

    public static T Of<T>() {
        if (!typeof(T).IsEnum)
            throw new InvalidOperationException("Must use Enum type");

        Array enumValues = Enum.GetValues(typeof(T));
        return (T)enumValues.GetValue(_Random.Next(enumValues.Length));
    }
}

[TestClass]
public class RandomTests {
    [TestMethod]
    public void TestMethod1() {
        Options option;
        for (int i = 0; i < 10; ++i) {
            option = RandomEnum.Of<Options>();
            Console.WriteLine(option);
        }
    }

}

Solution 11 - C#

You can also cast a random value:

using System;

enum Test {
  Value1,
  Value2,
  Value3
}

class Program {
  public static void Main (string[] args) {
    var max = Enum.GetValues(typeof(Test)).Length;
    var value = (Test)new Random().Next(0, max - 1);
    Console.WriteLine(value);
  }
}

But you should use a better randomizer like the one in this library of mine.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionmafuView Question on Stackoverflow
Solution 1 - C#Darin DimitrovView Answer on Stackoverflow
Solution 2 - C#mafuView Answer on Stackoverflow
Solution 3 - C#Aaron HudonView Answer on Stackoverflow
Solution 4 - C#Breno AngelottiView Answer on Stackoverflow
Solution 5 - C#Tim RobinsonView Answer on Stackoverflow
Solution 6 - C#borja garciaView Answer on Stackoverflow
Solution 7 - C#WHolView Answer on Stackoverflow
Solution 8 - C#Josie ThompsonView Answer on Stackoverflow
Solution 9 - C#NaeView Answer on Stackoverflow
Solution 10 - C#Dan ChampagneView Answer on Stackoverflow
Solution 11 - C#gsscoderView Answer on Stackoverflow