Làm cách nào để chọn giá trị ngẫu nhiên từ bảng liệt kê?


170

Đưa ra một phép liệt kê tùy ý trong C #, làm cách nào để chọn một giá trị ngẫu nhiên?

(Tôi không tìm thấy câu hỏi rất cơ bản này trên SO. Tôi sẽ đăng câu trả lời của mình trong một phút làm tài liệu tham khảo cho bất kỳ ai, nhưng xin vui lòng gửi câu trả lời của riêng bạn.)

Câu trả lời:


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

40
Hãy chắc chắn rằng bạn không tiếp tục tạo lại randomtrong một vòng lặp chặt chẽ - nếu không bạn sẽ tiếp tục nhận được cùng một giá trị.
ChrisF

1
Điều đó có nên ngẫu nhiên không. Tiếp theo (giá trị. Bước sóng -1)?
uriDium

7
@uriDium Không, đối số chỉ định giá trị nào là giá trị đầu tiên quá lớn để được trả về (tức là trừ tối đa 1 )
mafu

giá trị
Chiều dài

DarinDimitrov IMO bình luận đầu tiên của @ChrisF nên là một ghi chú bên trong câu trả lời với tín dụng cho Chris.
maytham-

60

Sử dụng Enum.GetValues ​​để lấy một mảng của tất cả các giá trị. Sau đó chọn một mục mảng ngẫu nhiên.

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

Kiểm tra:

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

Bạn chỉ có thể làm điều này:

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

Không cần lưu trữ mảng


GetNamestrả về một mảng.
Nathan Tuggy

Tôi có nghĩa là bạn không cần phải lưu trữ nó. Xấu của tôi
Breno Angelotti

Nếu ai đó đang thực hiện việc này trong một vòng lặp, họ sẽ gọi GetNames mỗi lần thay vì lưu nó vào một mảng. Điều này sẽ làm chậm mã của họ xuống vì vậy tôi không thấy đóng góp của bạn ở đây là gì?
Bojidar Stanchev

@BojidarStanchev NẾU , trong trường hợp của tôi, công việc này thật tuyệt vời, cảm ơn bạn Breno :)
Jaacko Torus

3

Đây là một phiên bản thay thế như là Extension Methodsử dụng 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());
        }
    }           
}

Hai
Một
Bốn
Bốn
Bốn
Ba
Hai
Bốn
Một
Ba


2

Gọi Enum.GetValues; cái này trả về một mảng đại diện cho tất cả các giá trị có thể cho enum của bạn. Chọn một mục ngẫu nhiên từ mảng này. Đúc mục đó trở lại loại enum ban đầu.


2

Đây là một chức năng chung cho nó. Giữ việc tạo RNG bên ngoài mã tần số cao.

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

Ví dụ sử dụng:

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

Có một phương thức tĩnh không phải là chủ đề an toàn là khá nguy hiểm.
CodeInChaos

@CodesInChaos Bạn nói đúng. Random.Next () không phải là chủ đề an toàn và sẽ bắt đầu trả về số 0 khi nó bị hỏng. Tôi đã cập nhật câu trả lời của tôi dựa trên thông tin này.
WHol

1

Cá nhân tôi là một fan hâm mộ của các phương thức mở rộng, vì vậy tôi sẽ sử dụng một cái gì đó như thế này (trong khi không thực sự là một tiện ích mở rộng, nó trông tương tự):

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
Kể từ C # 7.3, bạn có thể ràng buộc loại chung của mình là enum: public static T Of<T>() where T : Enum docs.microsoft.com/en-us/visualstudio/releasenotes/ trộm
nitzel

0

Thích nghi như một phần mở rộng lớp ngẫu nhiên:

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

Ví dụ về cách sử dụng:

var random = new Random();
var myEnumRandom = random.NextEnum<MyEnum>();

0

Bạn cũng có thể truyền một giá trị ngẫu nhiên:

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

Nhưng bạn nên sử dụng một bộ ngẫu nhiên tốt hơn như cái trong thư viện này của tôi.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.