ฉันจะเลือกค่าสุ่มจากการแจงนับได้อย่างไร


171

ด้วยการแจกแจงโดยพลการใน 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
ควรที่จะสุ่มถัดไป (ค่าความยาว -1)?
uriDium

7
@uriDium ไม่อาร์กิวเมนต์ระบุว่าค่าใดเป็นค่าแรกที่ใหญ่เกินกว่าจะส่งคืนได้ (เช่นค่าสูงสุดลบ 1 )
mafu

ค่าความยาว- 1
Bojidar Stanchev

DarinDimitrov IMO ความคิดเห็นแรกโดย @ChrisF ควรทราบภายในคำตอบด้วยเครดิตกับ Chris
maytham-ɯɐɥʇʎɐɯ

62

ใช้ 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ส่งกลับอาร์เรย์
นาธาน Tuggy

ฉันหมายความว่าคุณไม่จำเป็นต้องเก็บมันไว้ ไม่ดีของฉัน
Breno Angelotti

ถ้ามีคนทำแบบนี้ในลูปพวกเขาจะเรียก GetNames ทุกครั้งแทนที่จะใช้แคชในอาร์เรย์ นี่จะทำให้โค้ดช้าลงดังนั้นฉันไม่เห็นว่าคุณสนับสนุนอะไรที่นี่
Bojidar Stanchev

@BojidarStanchev ถ้าในกรณีของฉันนี้ทำงานที่ยอดเยี่ยมขอบคุณ Breno :)
Jaacko Torus

4

นี่คือทางเลือกที่รุ่นเป็นใช้ Extension MethodLINQ

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

สอง
หนึ่ง
สี่
สี่
สี่
สาม
สอง
สี่
หนึ่ง
สาม


2

โทรEnum.GetValues; ส่งคืนอาร์เรย์ที่แสดงค่าที่เป็นไปได้ทั้งหมดสำหรับ enum ของคุณ เลือกรายการแบบสุ่มจากอาร์เรย์นี้ ส่งรายการนั้นกลับไปเป็นประเภท enum ดั้งเดิม


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

มีวิธีคงที่ซึ่งไม่ใช่ threadsafe เป็นอันตรายสวย
CodesInChaos

@CodesInChaos คุณพูดถูก Random.Next () ไม่ใช่ threadsafe และจะเริ่มคืนค่าศูนย์เมื่อแตก ฉันได้อัปเดตคำตอบตามข้อมูลนี้แล้ว
58

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 คุณสามารถ จำกัด ประเภททั่วไปของคุณให้เป็น enum: 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.