2010-06-08 53 views
5

Giả sử tôi có một hàm chấp nhận một enum được trang trí bằng thuộc tính Flags. Nếu giá trị của enum là sự kết hợp của nhiều hơn một trong các phần tử enum thì làm thế nào tôi có thể trích xuất một trong những phần tử đó một cách ngẫu nhiên? Tôi có những điều sau đây nhưng có vẻ như phải có một cách tốt hơn.Giá trị ngẫu nhiên từ Flags enum

[Flags] 
enum Colours 
{ 
    Blue = 1, 
    Red = 2, 
    Green = 4 
} 

public static void Main() 
{ 
    var options = Colours.Blue | Colours.Red | Colours.Green; 
    var opts = options.ToString().Split(','); 
    var rand = new Random(); 
    var selected = opts[rand.Next(opts.Length)].Trim(); 
    var myEnum = Enum.Parse(typeof(Colours), selected); 
    Console.WriteLine(myEnum); 
    Console.ReadLine(); 
} 

Trả lời

8
var options = Colours.Blue | Colours.Green; 

var matching = Enum.GetValues(typeof(Colours)) 
        .Cast<Colours>() 
        .Where(c => (options & c) == c) // or use HasFlag in .NET4 
        .ToArray(); 

var myEnum = matching[new Random().Next(matching.Length)]; 
9

Bạn có thể gọi Enum.GetValues để có được một mảng các giá trị xác định của enum, như thế này:

var rand = new Random(); 

Colors[] allValues = (Colors[])Enum.GetValues(typeof(Colors)); 
Colors value = allValues[rand.Next(allValues.Length)]; 
+0

Tôi muốn một giá trị ngẫu nhiên chỉ có một tập hợp con của enum theo định nghĩa của một kết hợp bitwise như "Blue | Red". Xin lỗi vì không rõ ràng hơn. –

1

Nếu tôi hiểu đúng, câu hỏi là về trả lại một giá trị enum ngẫu nhiên từ một giá trị enum cờ , không trả lại một thành viên ngẫu nhiên từ một lá cờ enum.

[Flags] 
    private enum Shot 
    { 
     Whisky = 1, 
     Absynthe = 2, 
     Pochin = 4, 
     BrainEraser = Whisky | Absynthe | Pochin 
    } 

    [Test] 
    public void Test() 
    { 
     Shot myCocktail = Shot.Absynthe | Shot.Whisky; 

     Shot randomShotInCocktail = GetRandomShotFromCocktail(myCocktail); 
    } 

    private static Shot GetRandomShotFromCocktail(Shot cocktail) 
    { 
     Random random = new Random(); 

     Shot[] cocktailShots = Enum.GetValues(typeof(Shot)). 
      Cast<Shot>(). 
      Where(x => cocktail.HasFlag(x)).ToArray(); 

     Shot randomShot = cocktailShots[random.Next(0, cocktailShots.Length)]; 

     return randomShot; 
    } 

Sửa

Và rõ ràng bạn nên kiểm tra xem các enum là một giá trị hợp lệ, ví dụ .:

Shot myCocktail = (Shot)666; 

Sửa

Giản

+1

Bạn đúng trong việc nêu rõ vấn đề. Tuy nhiên tôi nghĩ rằng chức năng ngẫu nhiên của bạn sẽ không trả lại các giá trị với một phân phối đồng đều. Tại một cơ hội 50/50 cho mỗi giá trị thông qua các giá trị tiếp theo vòng lặp có một cơ hội thấp hơn được chọn? –

+0

Tôi thấy quan điểm của bạn. Nói đúng ra nó vẫn là ngẫu nhiên và trả lời câu hỏi của bạn. Tôi đã cập nhật nó lên một bản phân phối thậm chí. Đó là muộn và tôi chắc chắn rằng tôi có thể nhồi lên! :) –

+0

Và bây giờ đã được đơn giản hóa. –

2

tôi f bạn không quan tâm một chút đúc, và enum của bạn là loại int cơ bản, sau đây sẽ làm việc và nhanh chóng.

var rand = new Random(); 
const int mask = (int)(Colours.Blue | Colours.Red | Colours.Green); 
return (Colours)(mask & (rand.Next(mask) + 1)); 

Nếu bạn chỉ muốn một lá cờ duy nhất để được thiết lập, bạn có thể làm như sau:

var rand = new Random(); 
return (Colours)(0x1 << (rand.Next(3))); 
+0

Nếu kết quả của "(int) allValues ​​& rand.Next()" bằng 0, và bạn không có số không enum thành viên, bạn nhận được một enum tức là không hợp lệ (Màu) 0. –

+0

Đúng. Hãy để tôi xem nếu nó có thể được cố định ... – bbudge

+0

OK, tôi nghĩ nó hoạt động ngay bây giờ. Nhưng nó có chút lộn xộn và ít rõ ràng hơn. Chỉ hữu ích nếu hiệu suất là một mối quan tâm nghiêm trọng. – bbudge

Các vấn đề liên quan