2010-06-28 97 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