列挙からランダムな値を選択するにはどうすればよいですか?


170

C#で任意の列挙を指定した場合、ランダムな値を選択するにはどうすればよいですか?

(私はこの非常に基本的な質問をSOで見つけませんでした。私の回答をすぐに誰でも参照できるように投稿しますが、ご自分の回答を投稿してください。)

回答:


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

values.Length -1
Bojidar

DarinDimitrov IMO @ChrisFによる最初のコメントは、Chrisの功績による回答内のメモである必要があります。
メイサム-ɯɐɥʇʎɐɯ

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配列を返します。
Nathan Tuggy 2017年

保管する必要がないということです。私の悪い
Breno Angelotti

誰かがループでこれを行っている場合、配列にキャッシュするのではなく、毎回GetNamesを呼び出します。これはコードを遅くするので、ここであなたの貢献は何ですか?
Bojidar Stanchev

@BojidarStanchev IF、私の場合これは素晴らしい作品です、ありがとうブレノ:)
Jaacko Torus

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

Two
One
Four
Four
Four
Three
Two
Four
One
Three


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 2015

@CodesInChaosその通りです。Random.Next()はスレッドセーフではなく、ブレークするとゼロを返し始めます。この情報に基づいて回答を更新しました。
2015

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

しかし、私のライブラリのライブラリのようなより良いランダマイザーを使うべきです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.