2010-10-02 12 views
6

Mam następujący kod (przykład), a ja naprawdę nie wygodne z tylu „czy” kontroli:Bitowe flagi i instrukcja Switch?

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

Czy jest jakiś sposób, że mogę użyć „switch” oświadczenie. Może jeśli skonwertuję je na łańcuchy lub używam tablic?

+2

Wyrażenie 'switch' nie jest tym, czego potrzebujesz, ponieważ jest równoważne całemu pakietowi instrukcji' if ... else if ... else if ... ', co oczywiście nie jest tym, co masz. – Gabe

+5

Zauważ, że w C# 4.0 możesz użyć 'flag.HasFlag (Flags.p1)' zamiast 'flag & Flags.p1 == Flags.p1' – Gabe

+0

@Gabe: hivemind! –

Odpowiedz

7

Coś takiego?

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

EDIT: Jeśli kolejność działań są ważne, może być wymagana klauzula OrderBy.

+6

W C# 4.0 możesz użyć 'dict.Where (kv => flag.HasFlag (kv.Key))' –

+0

Podoba mi się @Ani, Dictionary i LINQ. Dzięki @Gabe i @Callum Rogers za wzmiankę o nowej funkcji C# 4.0. – kofucii

+0

Dobra odpowiedź, ale zdefiniuj wyszukiwanie akcji * poza * metodą. –

6

Oto wariacja na odpowiedź 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(); 
} 

Ważną różnicą jest to, że iteracje nad zdefiniowane wartości wyliczenia zamiast wpisów w słowniku. W ten sposób, jeśli dodasz nową flagę do wyliczenia bez dodawania jej do słownika, otrzymasz wyjątek przy próbie użycia nowej flagi. I zawsze iteruje w kolejności flag.