2010-06-28 71 views
125

鉴于C#中的任意枚举,我该如何选择一个随机值?如何从枚举中选择随机值?

(我没找到所以这个很基本的问题。我会后我的回答在一分钟内的任何人参考,但请随时发布自己的答案。)

回答

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

确保你不保持再造'在紧密循环random'虽然 - 否则,你将继续得到同样的值。 – ChrisF 2010-06-28 12:06:38

+0

应该是random.Next(values.Length -1)? – uriDium 2013-04-26 14:48:07

+3

@uriDium否,参数指定哪个值第一个太大而无法返回(即,_max减1_) – mafu 2013-09-11 10:50:56

47

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

static T RandomEnumValue<T>() 
{ 
    var v = Enum.GetValues (typeof (T)); 
    return (T) v.GetValue (new Random().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 

更新:这个答案原本是用来OrderBy (x => _Random.Next()).FirstOrDefault()选择一个随机元素。只有在你被不合理的吸引以随机键洗牌时才使用它。在任何其他情况下,请使用Darin Dimitrov接受的答案,而后将其纳入此答案中。

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

有一个不是线程安全的静态方法是非常危险的。 – CodesInChaos 2015-07-30 12:45:55

+0

@CodesInChaos你说得对。 Random.Next()不是线程安全的,当它中断时将开始返回零。我已根据此信息更新了我的答案。 – WHol 2015-08-04 15:23:52

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

} 
0

下面是使用LINQ的替代版本Extension Method

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

两个
一个






一个

1

你可能只是这样做:

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

无需存储阵列

+0

'GetNames'返回一个数组。 – 2017-06-13 15:21:01

+0

我的意思是说你不需要存储它。我的错 – 2017-06-13 16:35:08