C#で任意の列挙が与えられた場合、ランダムな値を選択するにはどうすればよいですか?
(私はこの非常に基本的な質問をSOで見つけませんでした。誰にでも参考として私の答えをすぐに投稿しますが、あなた自身の答えを投稿してください。)
Array values = Enum.GetValues(typeof(Bar));
Random random = new Random();
Bar randomBar = (Bar)values.GetValue(random.Next(values.Length));
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が受け入れた回答を使用します。これは後でこの回答に組み込みました。
あなたはこれを行うことができます:
var rnd = new Random();
return (MyEnum) rnd.Next(Enum.GetNames(typeof(MyEnum)).Length);
配列を保存する必要はありません
以下はそのための汎用関数です。 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>();
Enum.GetValues
を呼び出します;これは、enumのすべての可能な値を表す配列を返します。この配列からランダムなアイテムを選択します。そのアイテムを元の列挙型にキャストします。
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
四
四
四
三
二
四
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);
}
}
}