Comment sélectionner une valeur aléatoire à partir d'une énumération?
Étant donné une énumération arbitraire en C#, Comment puis-je sélectionner une valeur aléatoire?
(Je n'ai pas trouvé cette question très basique sur SO. Je posterai ma réponse dans une minute comme référence pour n'importe qui, mais n'hésitez pas à poster votre propre réponse.)
7 réponses
Array values = Enum.GetValues(typeof(Bar));
Random random = new Random();
Bar randomBar = (Bar)values.GetValue(random.Next(values.Length));
Utilisez Enum.GetValues pour récupérer un tableau de toutes les valeurs. Ensuite, sélectionnez un élément de tableau aléatoire.
static T RandomEnumValue<T> ()
{
var v = Enum.GetValues (typeof (T));
return (T) v.GetValue (new Random ().Next(v.Length));
}
Test:
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
Mise à jour: cette réponse utilisait à l'origine OrderBy (x => _Random.Next()).FirstOrDefault ()
pour sélectionner un élément aléatoire. Utilisez-le uniquement si vous êtes irrationnellement attiré par le brassage par des touches aléatoires. Dans tous les autres cas, utilisez plutôt la réponse acceptée par Darin Dimitrov, que j'ai incorporée dans cette réponse plus tard.
Appelez Enum.GetValues
; cela renvoie un tableau qui représente toutes les valeurs possibles pour votre énumération. Choisissez un élément aléatoire dans ce tableau. Renvoyez cet élément au type enum d'origine.
Voici une fonction générique pour elle. Gardez la création de RNG en dehors du code haute fréquence.
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);
}
}
Exemple d'Utilisation:
System.Windows.Forms.Keys randomKey = RandomEnum<System.Windows.Forms.Keys>();
Vous pouvez simplement faire ceci:
var rnd = new Random();
return (MyEnum) rnd.Next(Enum.GetNames(typeof(MyEnum)).Length);
Pas besoin de stocker des tableaux
Personnellement, je suis un fan des méthodes d'extension, donc j'utiliserais quelque chose comme ceci (bien que ce ne soit pas vraiment une extension, cela semble similaire):
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);
}
}
}
Voici une version alternative en tant que Extension Method
en utilisant 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());
}
}
}
Deux
Un
Quatre
Quatre
Quatre
Trois
Deux
Quatre
Un
Trois