2010-10-02 6 views
6

Tôi có đoạn code sau (chẳng hạn), và tôi thực sự không thoải mái với 'nếu' rất nhiều kiểm tra:Cờ bitwise và câu lệnh Chuyển đổi?

public enum Flags 
{ 
    p1 = 0x01, // 0001 
    p2 = 0x02, // 0010 
    p3 = 0x04, // 0100 
    p4 = 0x08 // 1000 
};  

public static void MyMethod (Flags flag) 
{ 
    if ((flag & Flags.p1) == Flags.p1) 
     DoSomething(); 

    if ((flag & Flags.p2) == Flags.p2) 
     DosomethingElse(); 

    if ((flag & Flags.p3) == Flags.p3) 
     DosomethingElseAgain(); 

    if ((flag & Flags.p4) == Flags.p4) 
     DosomethingElseAgainAndAgain(); 
} 

MyMethod(Flags.p1 | Flags.p3); 

Có một số cách, mà tôi có thể sử dụng một tuyên bố 'chuyển đổi'. Có lẽ nếu tôi chuyển đổi chúng thành chuỗi, hoặc sử dụng mảng?

+2

Câu lệnh 'switch' không phải là những gì bạn muốn vì nó tương đương với toàn bộ các câu lệnh' if ... else if ... else if ... ', rõ ràng không phải là những gì bạn có. – Gabe

+5

Lưu ý rằng trong C# 4.0 bạn có thể sử dụng 'flag.HasFlag (Flags.p1)' thay vì 'flag & Flags.p1 == Flags.p1' – Gabe

+0

@Gabe: hivemind! –

Trả lời

7

Một cái gì đó như thế này?

public static void MyMethod(Flags flag) 
{ 
    // Define action-lookup 
    var actionsByFlag = new Dictionary<Flags, Action> 
    { 
     { Flags.p1, DoSomething}, 
     { Flags.p2, DosomethingElse}, 
     { Flags.p3, DosomethingElseAgain}, 
     { Flags.p4, DosomethingElseAgainAndAgain}, 
    }; 

    // Find applicable actions 
    var actions = actionsByFlag.Where(kvp => (flag & kvp.Key) == kvp.Key) 
           .Select(kvp => kvp.Value); 

    //Execute applicable actions 
    foreach (var action in actions) 
     action(); 
} 

CHỈNH SỬA: Nếu thứ tự các hành động quan trọng, cần có mệnh đề OrderBy.

+6

Trong C# 4.0, bạn có thể sử dụng 'dict.Where (kv => flag.HasFlag (kv.Key))' –

+0

Tôi thích @Ani, Dictionary và LINQ. Nhờ @Gabe và @Callum Rogers đã đề cập đến tính năng C# 4.0 mới. – kofucii

+0

Câu trả lời hay, nhưng xác định hành động tra cứu * bên ngoài * phương pháp. –

6

Dưới đây là một biến thể của câu trả lời Ani 's:

public static void MyMethod(Flags flag) 
{ 
    // Define action-lookup 
    var dict = new Dictionary<Flags, Action> 
    { 
     { Flags.p1, DoSomething}, 
     { Flags.p2, DosomethingElse}, 
     { Flags.p3, DosomethingElseAgain}, 
     { Flags.p4, DosomethingElseAgainAndAgain}, 
    }; 

    // Find applicable actions 
    var actions = from value in Enum.GetValues(typeof(Flags)) 
        where flag.HasFlag(value) 
        select dict[value]; 

    //Execute applicable actions 
    foreach (var action in actions) 
     action(); 
} 

Sự khác biệt quan trọng ở đây là nó lặp qua các giá trị được định nghĩa trong liệt kê chứ không phải là các mục trong từ điển. Bằng cách đó nếu bạn thêm một lá cờ mới vào enum mà không thêm nó vào từ điển, bạn sẽ nhận được một ngoại lệ khi bạn cố gắng sử dụng cờ mới. Và nó luôn luôn lặp theo thứ tự cờ.