2011-05-20 9 views
5

Me gustaría escribir la opción enum o integer para pasar a mis métodos. ¿Hay un patrón o un método en C# para verificar si una opción (int 1,2,4,8, ...) es verdadera o falsa? Creo que debería ser posible fácilmente a través de funciones binarias.¿Hay un patrón o un método en C# para verificar si una opción (int 1,2,4,8, ...) es verdadera o falsa?

class Program 
{ 
    public enum Option 
    { 
     Option_A = 1, 
     Option_B = 2, 
     Option_C = 4, 
     Option_D = 8, 
    } 

    static void Main(string[] args) 
    { 
     int activeOption = 5; // Means I activeted the Option_A and Option_C 
     if (IsOption(activeOption, Option.Option_A)) { /*do work*/ } 
     if (IsOption(activeOption, Option.Option_B)) { /*do work*/ } 
     if (IsOption(activeOption, Option.Option_C)) { /*do work*/ } 
     if (IsOption(activeOption, Option.Option_D)) { /*do work*/ } 
    } 

    private static bool IsOption(int activeOption, Option option) 
    { 
     /*Evaluate if IsOption is true or false*/ 
     throw new NotImplementedException(); 
    } 
} 

EDITAR

Estoy limitado el número de opciones que puedo crear de esta manera?

+1

¿Por qué está utilizando una int en lugar de una opción? –

+0

@Martinho si nos fijamos en el ejemplo del código, es necesario seleccionar varias opciones.Un int es más eficiente en el uso del espacio que una colección de opciones. –

+1

@Robin: una opción enum es tan eficiente desde el punto de vista del espacio como una int. Adivina por qué: en realidad es un int. –

Respuesta

10

Debido a que su enumeración contiene banderas (o si se prefiere, es una campo de bits), se debe añadir un FlagsAttribute a ella:

[Flags] 
public enum Option 
{ 
    Option_A = 1, 
    Option_B = 2, 
    Option_C = 4, 
    Option_D = 8, 
} 

y luego, la comprobación se realiza normalmente con el operador AND. También se necesitará un yeso, porque está usando una variable int.

if(((Option)activeOption & Option.Option_A) != Option.Option_A) //... 

Si desea encapsular esta porquería de distancia, consulte el artículo relacionado en Smudge202's answer. Si está ejecutando .NET 4, ni siquiera necesita hacer eso: marque sehe's answer.

Pero realmente debería tratar de usar una variable de tipo Option directamente, y combinar las opciones con el operador binario OR:

Option activeOption = Option.Option_A | Option.Option_C; 

Por supuesto, el uso de este esquema limita el número de opciones que se pueden crear. Si lo deja como está, solo puede crear 32 opciones diferentes, porque int (el tipo subyacente predeterminado de una enumeración) tiene solo 32 bits. Si utiliza un long se puede tener 64 opciones diferentes:

[Flags] 
public enum Option : long 
{ 
    Option_A = 1, 
    Option_B = 2, 
    Option_C = 4, 
    Option_D = 8, 
    // blah blah 
} 

Sin embargo, si necesita un número arbitrario de opciones, es probable que sea hora de cambiar estrategias. Puede hacer un tipo personalizado que se comporte como una enumeración, pero probablemente será mejor con solo una enumeración regular que no sea una marca y un HashSet<Option>.

public enum Option 
{ 
    Option_A = 1, // notice the sequential values now 
    Option_B = 2, 
    Option_C = 3, 
    Option_D = 4, 
} 

HashSet<Option> options = new HashSet<Option> { Option.Option_A, Option.Option_C }; 
if(options.Contains(Option.Option_A)) // ... 
+1

+1 para atributo de banderas. El [enlace que publiqué] (http://www.codeproject.com/Articles/37921/Enums-Flags-and-Csharp-Oh-my-bad-pun.aspx) como respuesta muestra un método de extensión que puede usar para simplifica la escritura del código cuando pruebas para los miembros de enum que, con suerte, complementa tu respuesta. – Smudge202

+0

Completará la respuesta. Además, [C# 4.0 lo complementará] (http://stackoverflow.com/questions/6069869/is-there-a-pattern-or-a-method-inc-c-to-check-if-an-int- 1-2-4-8-option-is-t/6070172 # 6070172) – sehe

+0

@Martinho ¿Tengo limitada la cantidad de opciones que puedo crear de esta manera? –

3

Utilice Y a nivel de bits para verificar si los bits en option se configuran en activeOption. También es necesario que tanto los parámetros del mismo tipo que el operador va a trabajar (que son comprobación de los bits en una máscara de bits Option de todos modos):

private static bool IsOption(Option activeOption, Option option) 
{ 
    return (activeOption & option) == option; 
} 
+0

Aparece un error -> El operador '&' no se puede aplicar a los operandos de tipo 'int' –

+0

@Dran Dane: Necesita cambiar su sig de método para que ambos parámetros sean del mismo tipo. – BoltClock

+0

¿Estoy limitado al número de opciones que puedo crear de esta manera? –

2

Además de FlagsAttribute mencionado, en C# existe la Enum.HasFlag Method

using System; 

[Flags] public enum DinnerItems { 
    None = 0, 
    Entree = 1, 
    Appetizer = 2, 
    Side = 4, 
    Dessert = 8, 
    Beverage = 16, 
    BarBeverage = 32 
} 

public class Example 
{ 
    public static void Main() 
    { 
     DinnerItems myOrder = DinnerItems.Appetizer | DinnerItems.Entree | 
          DinnerItems.Beverage | DinnerItems.Dessert; 
     DinnerItems flagValue = DinnerItems.Entree | DinnerItems.Beverage; 
     Console.WriteLine("{0} includes {1}: {2}", 
         myOrder, flagValue, myOrder.HasFlag(flagValue)); 
    } 
} 
// The example displays the following output: 
// Entree, Appetizer, Dessert, Beverage includes Entree, Beverage: True 
1

Si está utilizando .NET 4.0 se puede utilizar HasFlag.

static void Main(string[] args) 
{ 
    Option activeOption = (Option)5; // Means I activeted the Option_A and Option_C 
    if (activeOption.HasFlag(Option.Option_A)) { /*do work*/ } 
    if (activeOption.HasFlag(Option.Option_B)) { /*do work*/ } 
    if (activeOption.HasFlag(Option.Option_C)) { /*do work*/ } 
    if (activeOption.HasFlag(Option.Option_D)) { /*do work*/ } 
} 
Cuestiones relacionadas