web-dev-qa-db-fra.com

Comment passez-vous plusieurs valeurs enum en C #?

Parfois, lors de la lecture du code C # d'autres personnes, je vois une méthode qui accepte plusieurs valeurs enum dans un seul paramètre. J'ai toujours pensé que c'était plutôt chouette, mais je n'y ai jamais pensé.

Eh bien, maintenant je pense en avoir besoin, mais je ne sais pas comment

  1. mettre en place la signature de la méthode pour accepter cette
  2. travailler avec les valeurs de la méthode
  3. définir l'énum

pour réaliser ce genre de chose.


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

Je souhaite pouvoir transmettre une ou plusieurs valeurs DayOfWeek à ma méthode. Est-ce que je pourrai utiliser cet enum tel quel? Comment puis-je faire les 3 choses énumérées ci-dessus?

110
Ronnie Overby

Lorsque vous définissez l'énumération, attribuez-la simplement avec [Flags], définissez les valeurs sur une puissance de deux et cela fonctionnera de cette façon.

Rien d'autre ne change, si ce n'est la transmission de plusieurs valeurs dans une fonction.

Par exemple:

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

Pour plus de détails, voir documentation de MSDN sur les types d'énumération .


Modifier en réponse aux ajouts à la question.

Vous ne pourrez pas utiliser cette énumération telle quelle, à moins que vous ne vouliez faire quelque chose comme la transmettre sous forme de tableau/collection/params. Cela vous laisserait passer plusieurs valeurs. La syntaxe des indicateurs nécessite que l’énumération soit spécifiée en tant qu’indicateur (ou que le langage soit bâti d’une manière qui n’a pas été conçue).

168
Reed Copsey

Je pense que la solution la plus élégante consiste à utiliser 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);
    }
75
Tillito

J'appuie la réponse de Reed. Toutefois, lors de la création de l'énumération, vous devez spécifier les valeurs de chaque membre de l'énum, ​​de manière à créer une sorte de champ de bits. Par exemple:

[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.
}
23
Jacob

Dans ma situation particulière, je voudrais utiliser le System.DayOfWeek

Vous ne pouvez pas utiliser System.DayOfWeek en tant que [Flags] énumération parce que vous n’avez aucun contrôle sur elle. Si vous souhaitez avoir une méthode qui accepte plusieurs DayOfWeek, vous devrez utiliser le mot clé 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 );

Sinon, vous pouvez créer votre propre [Flags] énumération décrite par de nombreux autres intervenants et utilise des comparaisons par bits.

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

Vous devez spécifier les nombres, et les incrémenter comme ceci, car il stocke les valeurs de manière binaire.

Ensuite, définissez simplement votre méthode pour prendre cette énumération

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

et l'appeler faire quelque chose comme

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

Pour vérifier si l’une des valeurs enum a été incluse, vérifiez-la à l’aide des opérations au niveau du bit, comme

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
  }
}
9
Tetraneutron
[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
    }

appeler la méthode dans ce format

MethodName (DaysOfWeek.Tuesday | DaysOfWeek.Thursday);

Implémentez une méthode EnumToArray pour obtenir les options passées

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
Rony

Marquez votre enum avec l'attribut [Flags]. Assurez-vous également que toutes vos valeurs s’excluent mutuellement (deux valeurs ne peuvent s’additionner), comme 1,2,4,8,16,32,64 dans votre cas.

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

Lorsque vous avez une méthode qui accepte une énumération DayOfWeek, utilisez bitwise ou operator (|) pour utiliser plusieurs membres ensemble. Par exemple:

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

Pour vérifier si le paramètre contient un membre spécifique, utilisez l'opérateur bitwise and (&) avec le membre que vous recherchez.

if(arg & DayOfWeek.Sunday == DayOfWeek.Sunday)
Console.WriteLine("Contains Sunday");
3
statenjason

Reed Copsey est correct et j'ajouterais au message d'origine si je pouvais, mais je ne peux pas, je vais donc devoir répondre à la place.

Il est dangereux de simplement utiliser [Drapeaux] sur n'importe quel ancien enum. Je crois que vous devez changer explicitement les valeurs enum en puissances de deux lorsque vous utilisez des drapeaux, afin d'éviter des conflits dans les valeurs. Voir le instructions pour FlagsAttribute et Enum .

2
Dan

Avec l'aide des réponses affichées et de celles-ci:

  1. FlagsAttribute Class (Regardez la comparaison entre utiliser et ne pas utiliser l'attribut [Flags])
  2. Attribut Enum Flags

J'ai l'impression de bien le comprendre.

Merci.

0
Ronnie Overby