2010-06-28 15 views
125

Dada una enumeración arbitraria en C#, ¿cómo selecciono un valor aleatorio?¿Cómo selecciono un valor aleatorio de una enumeración?

(no he encontrado esta pregunta muy básica sobre SO. Voy a publicar mi respuesta en un minuto como referencia para cualquier persona, pero por favor no dude en enviar su propia respuesta.)

Respuesta

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

Asegúrese de que usted no mantiene recreando 'random' en un bucle estrecho, aunque - lo contrario va a seguir recibiendo el mismo valor. – ChrisF

+0

¿Debería ser aleatorio.Siguiente (values.Length -1)? – uriDium

+3

@uriDium No, el argumento especifica qué valor es el primero en ser demasiado grande para ser devuelto (es decir_max menos 1_) – mafu

47

Use Enum.GetValues ​​a recuperar una matriz de todos los valores. Luego seleccione un elemento de matriz aleatorio.

static T RandomEnumValue<T>() 
{ 
    var v = Enum.GetValues (typeof (T)); 
    return (T) v.GetValue (new Random().Next(v.Length)); 
} 

prueba:

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 

Actualizado: Esta respuesta utilizado originalmente OrderBy (x => _Random.Next()).FirstOrDefault() para seleccionar un elemento aleatorio. Úselo solo si se siente irracionalmente atraído por las teclas aleatorias. En cualquier otro caso, utilice la respuesta aceptada por Darin Dimitrov en su lugar, que incorporé en esta respuesta más adelante.

2

Llame Enum.GetValues; esto devuelve una matriz que representa todos los valores posibles para su enumeración. Elige un elemento aleatorio de esta matriz. Vuelve a colocar ese elemento en el tipo de enumeración original.

2

Aquí hay una función genérica para ello. Mantenga la creación de RNG fuera del código de alta frecuencia. ejemplo

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

Uso:

System.Windows.Forms.Keys randomKey = RandomEnum<System.Windows.Forms.Keys>(); 
+0

Tener un método estático que no sea seguro para las roscas es bastante peligroso. – CodesInChaos

+0

@CodesInChaos Tienes razón. Random.Next() no es seguro para hilos y comenzará a devolver ceros cuando se rompe. He actualizado mi respuesta en base a esta información. – WHol

0

En lo personal, yo soy un fan de los métodos de extensión, por lo que usaría algo como esto (aunque no es realmente una extensión, tiene una apariencia similar):

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

Aquí hay una versión alternativa como Extension Method usando 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()); 
     } 
    }   
} 

Dos
Uno
Cuatro
Cuatro
Cuatro
Tres
Dos
Cuatro
Uno
Tres

1

Se podía hacer esto:

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

No hay necesidad de almacenar matrices

+0

'GetNames' devuelve una matriz. –

+0

Quise decir que no necesita almacenarlo. Mi error –

Cuestiones relacionadas