2010-10-02 10 views
6

Tengo el siguiente código (ejemplo), y estoy realmente no se siente cómodo con tantos 'si' cheques:Indicadores de bit a bit y declaración de cambio?

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

¿Hay alguna manera, que yo podría utilizar una sentencia 'interruptor'. ¿Tal vez si los convierto en cadenas o utilizo arreglos?

+2

Una declaración de 'cambio' no es lo que quieres porque es equivalente a un montón de instrucciones 'if ... else if ... else if ...', que claramente no es lo que tienes. – Gabe

+5

Tenga en cuenta que en C# 4.0 puede usar 'flag.HasFlag (Flags.p1)' en lugar de 'flag & Flags.p1 == Flags.p1' – Gabe

+0

@Gabe: hivemind! –

Respuesta

7

¿Algo como esto?

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: Si el orden de las acciones son importantes, una cláusula OrderBy puede ser requerida.

+6

En C# 4.0 puede usar 'dict.Where (kv => flag.HasFlag (kv.Key))' –

+0

Me gusta @Ani, Dictionary y LINQ. Gracias a @Gabe y @Callum Rogers por mencionar la nueva función C# 4.0. – kofucii

+0

Buena respuesta, pero define action-lookup * fuera * del método. –

6

Aquí hay una variación en la respuesta 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(); 
} 

La diferencia importante aquí es que itera sobre los valores definidos en la enumeración en lugar de las entradas en el diccionario. De esta forma, si agrega un nuevo indicador a la enumeración sin agregarlo al diccionario, obtendrá una excepción cuando intente usar el nuevo indicador. Y siempre itera en el orden de las banderas.