2010-06-28 14 views
125

Bei einer beliebigen Aufzählung in C#, wie wähle ich einen zufälligen Wert?Wie wähle ich einen zufälligen Wert aus einer Aufzählung?

(ich diese sehr grundsätzliche Frage auf SO nicht gefunden habe. Ich für alle meine Antwort in einer Minute als Referenz veröffentlichen werde, aber Sie fühlen sich frei, Ihre eigene Antwort zu schreiben.)

Antwort

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

Achten Sie darauf, nicht halten 'random' in einer engen Schleife neu zu erstellen, obwohl - sonst werden Sie behalten den gleichen Wert zu bekommen. – ChrisF

+0

Sollte das random.Next (values.Length -1) sein? – uriDium

+3

@uriDium Nein, das Argument gibt an, welcher Wert die erste zu groß sein, werden zurückgeführt (d.h._max minus 1_) – mafu

47

Verwenden Enum.GetValues ​​zu Ein Array aller Werte abrufen. Wählen Sie dann ein zufälliges Array-Objekt.

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 

Aktualisiert: Diese Antwort verwendet ursprünglich OrderBy (x => _Random.Next()).FirstOrDefault() ein zufälliges Element auszuwählen. Verwenden Sie es nur, wenn Sie irrational von zufälligen Schlüsseln angezogen werden. In jedem anderen Fall verwende stattdessen die angenommene Antwort von Darin Dimitrov, die ich später in diese Antwort aufgenommen habe.

2

Anruf Enum.GetValues; Dies gibt ein Array zurück, das alle möglichen Werte für Ihre Enumeration darstellt. Wählen Sie ein zufälliges Element aus diesem Array. Wirf das Element zurück zum ursprünglichen Enum-Typ.

2

Hier ist eine generische Funktion dafür. Halten Sie die RNG-Erstellung außerhalb des Hochfrequenzcodes.

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

Anwendungsbeispiel:

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

Eine statische Methode, die nicht threadsicher ist, ist ziemlich gefährlich. – CodesInChaos

+0

@CodesInChaos Sie haben Recht. Random.Next() ist nicht threadsafe und wird Nullen zurückgeben, wenn es bricht. Ich habe meine Antwort basierend auf diesen Informationen aktualisiert. – WHol

0
persönlich

, ich bin ein Fan von Erweiterungsmethoden, so würde ich so etwas wie diese verwenden (obwohl sie nicht wirklich eine Erweiterung, es sieht ähnlich aus):

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

Hier ist eine alternative Version als Extension MethodLINQ verwenden.

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

Zwei
Ein
Vier
Vier
Vier
Drei
Zwei
Vier
One
Drei

1

Sie können dies nur tun:

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

Keine Notwendigkeit Arrays zu speichern

+0

'GetNames' gibt ein Array zurück. –

+0

Ich meinte, dass Sie es nicht speichern müssen. Mein Fehler –

Verwandte Themen