如何从枚举中选择随机值?


170

给定C#中的任意枚举,如何选择随机值?

(我没有在SO上找到这个非常基本的问题。我将在一分钟内发布我的答案,以供任何人参考,但请随时发布您自己的答案。)

Answers:


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

40
但是,请确保不要一直random在紧缩循环中进行重新创建-否则,您将保持相同的价值。
克里斯·弗(ChrisF)

1
那应该是random.Next(values.Length -1)吗?
uriDium

7
@uriDium否,该参数指定哪个值是第一个太大而无法返回的值(即max减去1
mafu 2013年

values.Length -1
Bojidar Stanchev

IMO的DarinDimitrov IMO @ChrisF的第一条评论应该是答案中的注释,并应归功于Chris。
maytham-ɯɐɥʇʎɐɯ

60

使用Enum.GetValues检索所有值的数组。然后选择一个随机数组项。

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

测试:

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

5

您可以这样做:

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

无需存储阵列


GetNames返回一个数组。
内森·塔吉

我的意思是您不需要存储它。我的坏人
Breno Angelotti

如果有人在循环中执行此操作,他们将每次都调用GetNames而不是将其缓存在数组中。这会使他们的代码变慢,所以我看不到您在这里的贡献是什么?
Bojidar Stanchev

@BojidarStanchev 如果在我的情况下,这很好用,
谢谢布雷诺

3

这是Extension Methodusing 的替代版本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());
        }
    }           
}



四有
四有
四有

二有

有四有


2

致电Enum.GetValues; 这将返回一个表示您的枚举的所有可能值的数组。从此数组中选择一个随机项目。将该项目转换回原始的枚举类型。


2

这是它的通用功能。将RNG创建保持在高频代码之外。

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

用法示例:

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

拥有不是线程安全的静态方法非常危险。
CodesInChaos

@CodesInChaos你是对的。Random.Next()不是线程安全的,并且在中断时将开始返回零。我已根据此信息更新了答案。
WHol

1

就个人而言,我是扩展方法的粉丝,所以我会使用类似这样的东西(虽然不是真正的扩展,但看起来很相似):

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

}

1
从C#7.3开始,您可以将通用类型限制为枚举:public static T Of<T>() where T : Enum docs.microsoft.com/en-us/visualstudio/releasenotes/…–
nitzel

0

改编为随机类扩展:

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

用法示例:

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

0

您还可以强制转换一个随机值:

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

但是您应该使用更好的随机化程序,例如我的这个库中随机化程序

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.