125 votes

Comment passer plusieurs valeurs d'énumération en C# ?

Parfois, en lisant le code C# d'autres personnes, je vois une méthode qui accepte plusieurs valeurs d'énumération dans un seul paramètre. J'ai toujours pensé que c'était une bonne idée, mais je ne l'ai jamais étudiée.

Maintenant, je pense que j'en ai peut-être besoin, mais je ne sais pas comment

  1. configurer la signature de la méthode pour accepter cette
  2. travailler avec les valeurs de la méthode
  3. définir l'enum

pour réaliser ce genre de choses.


Dans ma situation particulière, je voudrais utiliser le System.DayOfWeek, qui est défini comme suit :

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

Je veux pouvoir passer une ou plusieurs des valeurs de DayOfWeek à ma méthode. Pourrai-je utiliser cet enum tel qu'il est ? Comment puis-je faire les trois choses énumérées ci-dessus ?

1 votes

Comme mentionné ci-dessous, vous pouvez utiliser un enum Flags. Vous pouvez consulter Les tenants et aboutissants des enums de C# qui contient plus d'informations sur le travail avec les enums Flags.

191voto

Reed Copsey Points 315315

Lorsque vous définissez l'enum, il suffit de l'attribuer avec [Flags], de définir des valeurs aux puissances de deux, et cela fonctionnera de cette façon.

Rien d'autre ne change, à part le fait de passer 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 cet enum tel quel, à moins que vous ne vouliez faire quelque chose comme le passer comme un tableau/collection/paramètre. Cela vous permettrait de passer plusieurs valeurs. La syntaxe flags exige que l'Enum soit spécifiée en tant que flags (ou de bâtarder le langage d'une manière qui n'est pas prévue).

9 votes

Je pense que si vous voulez que cela fonctionne, les valeurs doivent être définies comme des puissances de deux, un seul bit pour chaque valeur. Ce qui se passe, c'est que vous passez le OU bit à bit des valeurs dans le paramètre, que vous pouvez vérifier en utilisant les opérations ET bit à bit. Si vous ne prenez pas soin de définir les valeurs comme, par exemple, 1,2,4,8 etc, vous aurez des problèmes.

1 votes

Le fait de définir l'attribut Flags seul ne fonctionne pas automatiquement. Je viens de l'essayer.

1 votes

Vous avez raison, et j'ai supprimé la désinformation. J'ai aussi corrigé le code de Reed pour lui.

83voto

Tillito Points 2625

Je pense que la solution la plus élégante est d'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);
    }

0 votes

Il y a une autre chose importante à savoir, si vous le faites de cette façon : Cela ajoute beaucoup plus de flexibilité lorsque vous avez besoin de remplir votre enum dynamiquement. Par exemple : Si vous utilisez des cases à cocher pour définir les jours où vous voulez que votre programme s'exécute, et que vous essayez de le faire de la manière décrite ci-dessus, le code sera illisible. Donc, à la place, vous pouvez le faire de la façon suivante : ... DaysOfWeek days = new DaysOfWeek(); if (cbTuesday.Checked) days |= DaysOfWeek.Tuesday; if (cbWednesday.Checked) days |= DaysOfWeek.Wednesday; ...

31voto

Jacob Points 33729

Je soutiens la réponse de Reed. Cependant, lors de la création de l'énumération, vous devez spécifier les valeurs de chaque membre de l'énumération afin de 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.
}

1 votes

Il vous sera utile si vous devez un jour inspecter une valeur DaysOfWeek, par exemple si vous en lisez une qui est stockée dans une base de données. De plus, cela fournit une meilleure documentation aux autres programmeurs, puisque certains énumèrent les jours de la semaine à partir du lundi au lieu du dimanche.

3 votes

Pour des raisons de clarté et de maintenabilité, j'écrirais votre énumération 'All' comme suit : "Sunday|Monday|Tuesday|Wed Wednesday|Thurday|Friday|Saturday" et j'utiliserais une notation similaire pour 'Weekdays' et 'Weekend'.

0 votes

C'est bien si vous voulez créer votre propre enum, mais pour répondre à la question, vous ne pouvez pas modifier l'enum DaysOfWeek existant.

13voto

Robert Paulson Points 10792

Dans ma situation particulière, j'aurais j'aimerais utiliser la fonction System.DayOfWeek.

Vous ne pouvez pas utiliser le System.DayOfWeek en tant que [Flags] car vous n'avez aucun contrôle sur elle. Si vous souhaitez avoir une méthode qui accepte de multiples DayOfWeek alors vous devrez utiliser l'option params mot-clé

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] comme indiqué par de nombreux autres intervenants et utiliser des comparaisons par bit.

2 votes

Je ne sais pas pourquoi je n'ai pas pensé aux paramètres. Cela devrait être très utile pour utiliser des enums qui ne sont pas des champs de bits.

0 votes

Brillant je me suis sauvé grâce à vous.

11voto

Tetraneutron Points 8494
[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 parce qu'il stocke les valeurs par bit.

Ensuite, définissez simplement votre méthode pour prendre cet enum.

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

et pour l'appeler, faites quelque chose comme

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

Pour vérifier si une des valeurs de l'enum a été incluse, vérifiez-les en utilisant des opérations de type bitwise 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
  }
}

0 votes

Ça ne répond pas à la question. "Dans ma situation particulière, je voudrais utiliser le System.DayOfWeek"

0 votes

Mais c'est exactement ce que je cherchais. Alors merci quand même.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X