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

问题描述 投票:0回答:11

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

(我没有在SO上找到这个非常基本的问题。我会在一分钟内发布我的答案作为任何人的参考,但请随意发布你自己的答案。)

c# random enums
11个回答
358
投票
Array values = Enum.GetValues(typeof(Bar));
Random random = new Random();
Bar randomBar = (Bar)values.GetValue(random.Next(values.Length));

83
投票

使用 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

8
投票

这是使用

Extension Method
作为
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());
        }
    }           
}

两个
一个




两个

一个


7
投票

改编为随机类扩展:

public static class RandomExtensions
{   
    public static T NextEnum<T>(this Random random)
        where T : struct, Enum
    {
        var values = Enum.GetValues<T>();

        return values[random.Next(values.Length)];
    }
}

使用示例:

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

5
投票

你可以这样做:

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

无需存储数组


4
投票

致电

Enum.GetValues
;这将返回一个数组,表示枚举的所有可能值。从该数组中随机选择一个项目。将该项目恢复为原始枚举类型。


3
投票

现代答案结合了这个答案其评论

var randomMyEnum = GetRandom<MyEnum>();

实施:

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

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

1
投票

其中很多答案都相当古老,并且 - 如果我错了,请纠正我 - 似乎适用于一些粗略的概念,例如类型擦除和动态类型转换。然而,正如用户 Yarek T 指出的那样,对于 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)];
}

或者,就像 borja garcia 的回答一样,我们甚至可以将其写为随机类的扩展

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

我们可以从mafu的答案运行相同的测试

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

潜在产出:

Thursday
Saturday
Sunday
Sunday
Sunday
Saturday
Wednesday
Monday
Wednesday
Thursday

0
投票

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

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
投票

您还可以投射随机值:

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

但是你应该使用更好的随机化器,就像我的这个中的那样。

© www.soinside.com 2019 - 2024. All rights reserved.