2008-11-26 10 views
23

Podría alguien indicarme un método más limpio para generar un miembro enum aleatorio. Esto funciona, pero parece feo.Generar enumeración aleatoria en C# 2.0

Gracias!

public T RandomEnum<T>() 
{ 
    string[] items = Enum.GetNames(typeof(T)); 
    Random r = new Random(); 
    string e = items[r.Next(0, items.Length - 1)]; 
    return (T)Enum.Parse(typeof (T), e, true); 
} 

Respuesta

40
public T RandomEnum<T>() 
{ 
    T[] values = (T[]) Enum.GetValues(typeof(T)); 
    return values[new Random().Next(0,values.Length)]; 
} 

Gracias a @ [Marc Gravell] para ponting que la max en Random.Next (min, max) es exclusiva.

+3

Por supuesto, en una implementación real no se desea utilizar un nuevo aleatoria cada llamada (especialmente si se llama a menudo) y yo personalmente desearía caché de la matriz. – Dolphin

+1

Tenga en cuenta que Silverlight no tiene Enum.GetValues. Vea la solución alternativa más abajo. –

+2

CUIDADO Esta respuesta es defectuosa. Como se dijo antes, si la generación está unida, esto no generará ninguna aleatoriedad. – Luis

14

La respuesta de Marxidad es buena (obsérvese que solo necesita Next(0,values.Length), ya que el límite superior es exclusivo), pero tenga cuidado con el tiempo. Si haces esto en un ciclo cerrado, obtendrás muchas repeticiones. Para que sea más aleatorio, considerar mantener el objeto aleatorio en un campo - es decir,

private Random rand = new Random(); 
public T RandomEnum<T>() 
{ 
    T[] values = (T[]) Enum.GetValues(typeof(T)); 
    return values[rand.Next(0,values.Length)]; 
} 

Si se trata de un campo estático, necesitará para sincronizar el acceso.

+0

En mi caso, es solo generar algunos valores predeterminados para un juego, sin bucles en absoluto. ¡Gracias por el consejo! – user10178

0

No estoy seguro acerca de C# pero otros lenguajes permiten huecos en los valores enum. Para dar cuenta de eso:

enum A {b=0,c=2,d=3,e=42}; 

switch(rand.Next(0,4)) 
{ 
    case 0: return A.b; 
    case 1: return A.c; 
    case 2: return A.d; 
    case 3: return A.e; 
} 

¡El inconveniente principal es mantenerlo actualizado!

No está tan ordenado pero es más correcto en esa caja de esquina.


Como se señaló, los ejemplos de arriba se indexan en una matriz de valores válidos y esto lo hace bien. OTOH algunos idiomas (tos D tos) no proporcionan esa matriz por lo que lo anterior es lo suficientemente útil como para dejarlo de todos modos.

+0

cuentas de marxidad devolviendo un índice de matriz no el valor de la enumeración. ¡Hice lo mismo, acabo de tomar la ruta escénica! – user10178

+0

Eso podría haber sido más claro. La enumeración se genera por su posición en la matriz, no por su valor. – user10178

3

Silverlight no tiene GetValues ​​(), pero puede usar la reflexión para obtener una enumeración aleatoria.

private Random rnd = new Random(); 

public T RndEnum<T>() 
{ 
    FieldInfo[] fields = typeof(T).GetFields(BindingFlags.Static | BindingFlags.Public); 

    int index = rnd.Next(fields.Length); 

    return (T) Enum.Parse(typeof(T), fields[index].Name, false); 
} 
+0

¡Gracias, necesitaba esto para Silverlight! –

0
Enum.Parse(typeof(SomeEnum), mRandom.Next(min, max).ToString()).ToString() 
+0

Este método no funciona si hay espacios entre los valores numéricos de los valores de Enum (y eso es bastante posible). – Styxxy