35 votes

Drapeaux énumération et opérations au niveau des bits vs.

Un autre développeur nous a suggéré de magasin une sélection des jours de la semaine, 7-chaîne de caractères de 1 et de 0, c'est à dire "1000100" pour le lundi et le vendredi. J'ai préféré (et fortement recommandé) d'une solution avec un Drapeaux enum et les opérations bit à bit, je pense que c'est une façon plus propre de faire cela, et il devrait être plus facile à comprendre pour les autres développeurs.

  [Flags()]
  public enum Weekdays : int
  {
    Monday = 1,
    Tuesday = 2,
    Wednesday = 4,
    Thursday = 8,
    Friday = 16,
    Saturday = 32,
    Sunday = 64
  }

Cependant, comme j'ai commencé à mettre en œuvre une solution d'exemple, j'ai réalisé que peut-être la simple chaîne de caractères approche était plus facile après tout: Certainement la bit-chaîne est de plus évident que "17" si vous êtes juste en regardant les données. Et je trouve que le C# les opérations bit à bit contre-intuitif et extrêmement détaillé:

Weekdays workDays = Weekdays.Monday | Weekdays.Tuesday;
if ((workDays & Weekdays.Monday) == Weekdays.Monday) 
{...}

Bien sûr, cela pourrait être enveloppé bien dans les méthodes d'extension, mais ensuite, nous avons subitement à la fin avec au moins le même nombre de lignes de code comme avec la chaîne-de la solution, et j'ai du mal à argumenter en faveur de la bit-à-bit de code est plus facile à lire.

Cela étant dit, je voudrais aller avec des drapeaux enum et les opérations bit à bit. Les principaux avantages que je peux penser sont

  • De meilleures performances
  • Moins d'espace nécessaire pour le stockage

Alors, comment puis-je vendre de l'or au niveau du bit solution à mes collègues? Devrais-Je? Quels sont les autres avantages de l'utilisation de cette méthode sur les chaînes? Après avoir terminé l'exemple de projet, j'ai trouvé que l'équipe a encore opté pour la chaîne à la solution. J'ai besoin d'un peu mieux/plus d'arguments. Pourquoi devriez-vous utiliser les Drapeaux des enums, plutôt que de simples bits-chaînes?

41voto

Tuzo Points 14234

Avantages de l'utilisation de Drapeaux enum:

Des négatifs de l'utilisation de Drapeaux enum:

  • La représentation des données pour l'homme dur à comprendre (par exemple, quels indicateurs sont définis pour 17?)


Avantages de l'utilisation de la chaîne de bits:

  • Facile pour les programmeurs de voir les bits sont définis dans le string

Négatifs de l'aide de la chaîne de bits:

  • Non-approche standard
  • Plus difficile à comprendre pour les programmeurs familier avec votre conception
  • Potentiellement plus facile de mettre la "poubelle" des valeurs (par exemple, stringValue = "dimanche")
  • Inutile de la chaîne de création
  • Inutile d'analyse de chaînes
  • De travail de développement
  • Réinventer la roue (mais même pas un tour de roue)


Comment important est-il vraiment être en mesure de regarder la chaîne de bits pour voir ce qui est prévu? Si il est difficile de savoir qui 17 est le lundi et le vendredi, vous pouvez toujours utiliser la calculatrice et de les convertir en binaire. Ou ajouter une sorte de représentation de chaîne pour "afficher" (ou de débogage) d'utilisation. Ce n'est pas que difficile.


Il me semble aussi que si vous allez faire de la chaîne de bits approche solide, alors vous aurez besoin pour faire un peu d'encapsulation pour l'amener à un niveau d'abstraction que les Drapeaux enum offre déjà. Si l'approche est tout simplement de manipuler la chaîne de bits directement alors que va être dur à lire (et comprendre) et probablement sujettes à erreur.

par exemple, vous pouvez voir ceci:

days = "1000101"; // fixed bug where days were incorrectly set to "1010001"

23voto

Imagist Points 5348

Vous ne devriez pas créer de structures de données non standard pour remplacer une structure de données standard (dans ce cas, l'en-tête intégré DayOfWeek). Au lieu de cela, étendez la structure existante. Cela fonctionne essentiellement de la même manière que la méthode de drapeaux à bits dont vous parliez.

 namespace ExtensionMethods
{
    public static class Extensions
    {
        /*
         * Since this is marked const, the actual calculation part will happen at
         * compile time rather than at runtime.  This gives you some code clarity
         * without a performance penalty.
         */
        private const uint weekdayBitMask =
            1 << Monday 
            | 1 << Tuesday
            | 1 << Wednesday
            | 1 << Thursday
            | 1 << Friday;
        public static bool isWeekday(this DayOfWeek dayOfWeek)
        {
            return 1 << dayOfWeek & weekdayBitMask > 0;
        }
    }   
}
 

Maintenant, vous pouvez faire ce qui suit:

 Thursday.isWeekday(); // true
Saturday.isWeekday(); // false
 

6voto

Guffa Points 308133

Faites un cours pouvant contenir la combinaison des jours de la semaine. Dans la classe, vous pouvez représenter les données de toute façon, mais je choisirais certainement une énumération de drapeaux plutôt qu'une chaîne. En dehors de la classe, vous utilisez simplement les valeurs enum et la logique réelle est encapsulée dans la classe.

Quelque chose comme:

 [Flags]
public enum Days {
   Monday = 1,
   Tuesday = 2,
   Wednesday = 4,
   Thursday = 8,
   Friday = 16,
   Saturday = 32,
   Sunday = 64,
   MondayToFriday = 31,
   All = 127,
   None = 0
}

public class Weekdays {

   private Days _days;

   public Weekdays(params Days[] daysInput) {
      _days = Days.None;
      foreach (Days d in daysInput) {
         _days |= d;
      }
   }

   public bool Contains(Days daysMask) {
      return (_days & daysMask) == daysMask;
   }

   public bool Contains(params Days[] daysMasks) {
      Days mask = Days.None;
      foreach (Days d in daysMasks) {
         mask |= d;
      }
      return (_days & mask) == mask;
   }

}
 

Exemple d'utilisation:

 Weekdays workdays = new Weekdays(Days.MondayToFriday);
if (workdays.Contains(Days.Monday, Days.Wednesday)) {
   ...
}
 

1voto

Rex M Points 80372

La question devrait être centrée autour de savoir si les yeux de l'homme ne sera jamais réellement voir cette valeur stockée. Si oui, un peu format lisible par l'homme est de toute évidence important (bien que si c'est le cas, je ferais un argument pour quelque chose d'encore plus grand, comme un tableau de la journée noms).

Cependant, au moins dans toutes les applications que j'ai jamais construit, ce type de données va dans un petit champ quelque part et n'est jamais vu de nouveau, sauf via le code c# qui signifie bitflags sont certainement le plus simple - ils sont le plus lisible dans le code. Vos collègues vraiment envie d'écrire une chaîne de caractères de l'analyseur que les cartes de 0 et de 1 pour les valeurs au lieu d'utiliser le construit en et utilisé pour les+ de 40 ans idée des opérations bit à bit?

0voto

Noon Silk Points 30396

Curieusement, ces deux méthodes sont exactement les mêmes. seule la méthode des drapeaux est plus évidente.

Personnellement, je choisirais les drapeaux (bien que potentiellement, selon votre modèle, il serait préférable de stocker la liste sous forme de liste contre son détenteur).

-- Modifier

Et pour être clair, la performance n'a vraiment pas besoin d'être prise en compte pour ce que vous faites, je pense. Donc, allez simplement avec le plus lisible. (Qui, à mon humble avis, est les drapeaux nommés).

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