2009-06-23 12 views
96

Algunas veces, al leer el código C# de otros, veo un método que aceptará múltiples valores enum en un solo parámetro. Siempre pensé que era algo ordenado, pero nunca lo analicé.¿Cómo se pasan múltiples valores enum en C#?

Bueno, ahora creo que puede tener una necesidad de ella, pero no saben cómo

  1. creó la firma del método para aceptar este
  2. trabajo con los valores en el método
  3. define la enumeración

para lograr este tipo de cosas.


En mi situación particular, me gustaría utilizar el System.DayOfWeek, que se define como:

[Serializable] 
[ComVisible(true)] 
public enum DayOfWeek 
{ 
    Sunday = 0, 
    Monday = 1, 
    Tuesday = 2, 
    Wednesday = 3, 
    Thursday = 4, 
    Friday = 5,  
    Saturday = 6 
} 

Quiero ser capaz de pasar uno o más de los valores DAYOFWEEK a mi método. ¿Podré usar esta enumeración particular tal como es? ¿Cómo hago las 3 cosas enumeradas arriba?

+1

Como se menciona más adelante, se puede utilizar una enumeración Banderas.Es posible que desee verificar [Los detalles de C# enumeraciones] (http://www.codeducky.org/ins-outs-c-enums/), que contiene más información sobre cómo trabajar con las enumeraciones de Flags. – ChaseMedallion

Respuesta

151

Cuando define la enumeración, simplemente la atribuye con [Banderas], establezca valores en potencias de dos, y funcionará de esta manera.

Nada más cambia, aparte de pasar múltiples valores en una función.

Por ejemplo:

[Flags] 
enum DaysOfWeek 
{ 
    Sunday = 1, 
    Monday = 2, 
    Tuesday = 4, 
    Wednesday = 8, 
    Thursday = 16, 
    Friday = 32, 
    Saturday = 64 
} 

public void RunOnDays(DaysOfWeek days) 
{ 
    bool isTuesdaySet = (days & DaysOfWeek.Tuesday) == DaysOfWeek.Tuesday; 

    if (isTuesdaySet) 
     //... 
    // Do your work here.. 
} 

public void CallMethodWithTuesdayAndThursday() 
{ 
    this.RunOnDays(DaysOfWeek.Tuesday | DaysOfWeek.Thursday); 
} 

Para más detalles, véase MSDN's documentation on Enumeration Types.


Editar en respuesta a las preguntas añadidas.

No podrá usar esa enumeración como está, a menos que desee hacer algo así como pasarlo como una matriz/colección/params. Eso te permitiría pasar múltiples valores. La sintaxis de los indicadores requiere que Enum se especifique como indicadores (o para bastardear el idioma de una manera que no está diseñada).

+3

¡GUAU! ¡Lo entendiste rápido! –

+9

Creo que si quieres que esto funcione, los valores deben definirse como potencias de dos, un solo bit para cada valor. Lo que sucede es que se pasa el OR bit a bit de los valores en el parámetro, que se puede verificar usando operaciones Y a nivel de bit. Si no se ocupa de definir los valores como, por ejemplo, 1,2,4,8, etc., tendrá problemas. –

+1

El solo establecimiento del atributo Flags por sí solo no funciona automáticamente. Lo intenté. –

0

Algo de esta naturaleza debe mostrar lo que busca:

[Flags] 
public enum SomeName 
{ 
    Name1, 
    Name2 
} 

public class SomeClass() 
{ 
    public void SomeMethod(SomeName enumInput) 
    { 
     ... 
    } 
} 
+3

No funcionará sin especificar valores en potencias de 2. –

21

Me segunda respuesta de Reed. Sin embargo, al crear la enumeración, debe especificar los valores para cada miembro enum, por lo que constituye un campo de tipo de bit. Por ejemplo:

[Flags] 
public enum DaysOfWeek 
{ 
    Sunday = 1, 
    Monday = 2, 
    Tuesday = 4, 
    Wednesday = 8, 
    Thursday = 16, 
    Friday = 32, 
    Saturday = 64, 

    None = 0, 
    All = Weekdays | Weekend, 
    Weekdays = Monday | Tuesday | Wednesday | Thursday | Friday, 
    Weekend = Sunday | Saturday, 
    // etc. 
} 
+1

Te ayudará si alguna vez necesitas inspeccionar un valor de DaysOfWeek, por ejemplo, si estás leyendo uno almacenado en una base de datos. Además, proporciona una mejor documentación a otros programadores, ya que algunos enumeran días de la semana a partir de lunes en lugar de domingo. – Jacob

+3

Para mayor claridad y facilidad de mantenimiento, escribiría su enumeración 'Todos' como "Domingo | Lunes | Martes | Miércoles | Jueves | Viernes | Sábados" ... y usaría una notación similar para 'Días de la semana' y 'Fin de semana'. –

+0

Buen punto. Eso es mejor. – Jacob

2
[Flags] 
    public enum DaysOfWeek{ 


     Sunday = 1 << 0, 
     Monday = 1 << 1, 
     Tuesday = 1 << 2, 
     Wednesday = 1 << 3, 
     Thursday = 1 << 4, 
     Friday = 1 << 5, 
     Saturday = 1 << 6 
    } 

llamada al método en este formato

MethodName (DaysOfWeek.Tuesday | DaysOfWeek.Thursday);

implementar un método EnumToArray para obtener las opciones pasó

private static void AddEntryToList(DaysOfWeek days, DaysOfWeek match, List<string> dayList, string entryText) { 
      if ((days& match) != 0) { 
       dayList.Add(entryText); 
      } 
     } 

     internal static string[] EnumToArray(DaysOfWeek days) { 
      List<string> verbList = new List<string>(); 

      AddEntryToList(days, HttpVerbs.Sunday, dayList, "Sunday"); 
      AddEntryToList(days, HttpVerbs.Monday , dayList, "Monday "); 
      ... 

      return dayList.ToArray(); 
     } 
+3

Interesante pero innecesario. –

+0

No responde la pregunta. "En mi situación particular, me gustaría usar System.DayOfWeek" –

+0

Gracias, Robert, pero realmente no tiene que señalar esto en cada respuesta. –

9
[Flags] 
public enum DaysOfWeek 
{ 
    Mon = 1, 
    Tue = 2, 
    Wed = 4, 
    Thur = 8, 
    Fri = 16, 
    Sat = 32, 
    Sun = 64 
} 

Se tiene que especificar los números, y el incremento ellos de esta manera, ya que es el almacenamiento de los valores de una forma bit a bit.

A continuación, sólo definen el método de tomar esta enumeración

public void DoSomething(DaysOfWeek day) 
{ 
    ... 
} 

y llamarlo hacer algo como

DoSomething(DaysOfWeek.Mon | DaysOfWeek.Tue) // Both Monday and Tuesday 

Para comprobar si uno de los valores de enumeración se incluyó comprobarlas usando operaciones bit a bit como

public void DoSomething(DaysOfWeek day) 
{ 
    if ((day & DaysOfWeek.Mon) == DaysOfWeek.Mon) // Does a bitwise and then compares it to Mondays enum value 
    { 
    // Monday was passed in 
    } 
} 
+0

No responde la pregunta. "En mi situación particular, me gustaría utilizar System.DayOfWeek" –

+0

Pero es exactamente lo que he estado buscando. Así que gracias de todos modos. – Tillito

3

Marque su enum con el atributo [Flags]. También asegúrese de que todos sus valores son excluyentes entre sí (dos valores no se pueden añadir hasta igualar otra) como 1,2,4,8,16,32,64 en su caso

[Flags] 
public enum DayOfWeek 
{ 
Sunday = 1, 
Monday = 2, 
Tuesday = 4, 
Wednesday = 8, 
Thursday = 16, 
Friday = 32,  
Saturday = 64 
} 

Cuando se tiene una método que acepta una enumeración DayOfWeek utiliza el operador bit a bit (|) para usar múltiples miembros juntos. Por ejemplo:

MyMethod(DayOfWeek.Sunday|DayOfWeek.Tuesday|DayOfWeek.Friday) 

Para comprobar si el parámetro contiene un miembro específico, utilice el nivel de bits y operador (&) con el miembro que está mirando para.

if(arg & DayOfWeek.Sunday == DayOfWeek.Sunday) 
Console.WriteLine("Contains Sunday"); 
+0

No responde la pregunta. "En mi situación particular, me gustaría utilizar System.DayOfWeek" –

2

Reed Copsey es correcta y que se sumaría a la entrada original si pudiera, pero no puedo, así que tendrá lugar para responder.

Es peligroso usar [Banderas] en cualquier enumeración anterior. Creo que tienes que cambiar explícitamente los valores enum a potencias de dos cuando uses banderas, para evitar conflictos en los valores. Vea el guidelines for FlagsAttribute and Enum.

0

Con la ayuda de las respuestas publicadas y éstos:

  1. FlagsAttribute Class (Mira la comparación de usar y no usar el [Banderas] atributo)
  2. Enum Flags Attribute

me siento como Lo entiendo bastante bien.

Gracias.

11

En mi situación particular, me gustaría usar la System.DayOfWeek

No se puede utilizar el System.DayOfWeek como una enumeración [Flags] porque no tiene control sobre él. Si usted desea tener un método que acepta múltiples DayOfWeek entonces usted tendrá que utilizar la palabra clave params

void SetDays(params DayOfWeek[] daysToSet) 
{ 
    if (daysToSet == null || !daysToSet.Any()) 
     throw new ArgumentNullException("daysToSet"); 

    foreach (DayOfWeek day in daysToSet) 
    { 
     // if(day == DayOfWeek.Monday) etc .... 
    } 
} 

SetDays(DayOfWeek.Monday, DayOfWeek.Sunday); 

De lo contrario puede crear su propia enumeración [Flags] como se indica por numerosos otro personal de respuesta y el uso de comparaciones a nivel de bit.

+1

No sé por qué no pensé en params. Eso debería ser muy útil para usar enumeraciones que no son bitfields. –

63

creo que la solución más elegante es usar HasFlag():

[Flags] 
    public enum DaysOfWeek 
    { 
     Sunday = 1, 
     Monday = 2, 
     Tuesday = 4, 
     Wednesday = 8, 
     Thursday = 16, 
     Friday = 32, 
     Saturday = 64 
    } 

    public void RunOnDays(DaysOfWeek days) 
    { 
     bool isTuesdaySet = days.HasFlag(DaysOfWeek.Tuesday); 

     if (isTuesdaySet) 
     { 
      //... 
     } 
    } 

    public void CallMethodWithTuesdayAndThursday() 
    { 
     RunOnDays(DaysOfWeek.Tuesday | DaysOfWeek.Thursday); 
    } 
+5

Esto es posible desde Framework 4.0 en. – Tillito

Cuestiones relacionadas