De temps en temps, je vois une énumération comme celle-ci:
[Flags]
public enum Options
{
None = 0,
Option1 = 1,
Option2 = 2,
Option3 = 4,
Option4 = 8
}
Je ne comprends pas exactement ce que fait l' [Flags]
attribut.
Quelqu'un at-il une bonne explication ou un exemple qu'il pourrait publier?
CatAndDog = Cat | Dog
(le OU logique au lieu du Conditionnel), je suppose?Réponses:
L'
[Flags]
attribut doit être utilisé chaque fois que l'énumérable représente une collection de valeurs possibles, plutôt qu'une seule valeur. Ces collections sont souvent utilisées avec des opérateurs au niveau du bit, par exemple:Notez que l'
[Flags]
attribut ne permet pas cela par lui-même - tout ce qu'il fait est de permettre une belle représentation par la.ToString()
méthode:Il est également important de noter que les valeurs d'énumération
[Flags]
ne sont pas automatiquement égales à deux. Si vous omettez les valeurs numériques, l'énumération ne fonctionnera pas comme on pourrait s'y attendre dans les opérations au niveau du bit, car par défaut, les valeurs commencent par 0 et incrémentent.Déclaration incorrecte:
Les valeurs, si elles sont déclarées de cette façon, seront Jaune = 0, Vert = 1, Rouge = 2, Bleu = 3. Cela le rendra inutile en tant que drapeaux.
Voici un exemple de déclaration correcte:
Pour récupérer les valeurs distinctes de votre propriété, on peut le faire:
ou avant .NET 4:
Sous les couvertures
Cela fonctionne parce que vous avez utilisé des pouvoirs de deux dans votre énumération. Sous les couvertures, vos valeurs d'énumération ressemblent à ceci en binaires et en zéros:
De même, une fois que vous avez défini votre propriété AllowedColors sur Rouge, Vert et Bleu à l'aide de l'
|
opérateur binaire OR au niveau du bit , AllowedColors ressemble à ceci:Ainsi, lorsque vous récupérez la valeur que vous effectuez réellement au niveau du bit ET
&
sur les valeurs:La valeur None = 0
Et concernant l'utilisation de
0
dans votre énumération, citant MSDN:Vous pouvez trouver plus d'informations sur l'attribut flags et son utilisation sur msdn et sur la conception de flags sur msdn
la source
ToString
mise en œuvre de votre ENUM utilise Flags, et ainsi neEnum.IsDefined
,Enum.Parse
etc. Essayez de supprimer Drapeaux et regardez le résultat de MyColor.Yellow | MyColor.Red; sans elle, vous obtenez «5», avec des drapeaux, vous obtenez «jaune, rouge». Certaines autres parties du framework utilisent également [Flags] (par exemple, la sérialisation XML).myProperties.AllowedColors = MyColor.Red | MyColor.Green | MyColor.Blue;
. Vous pouvez faire:myProperties.AllowedColors = myProperties.AllowedColors ^ MyColor.Blue //myProperties.AllowedColors == MyColor.Red | Mycolor.Green
Vous pouvez aussi faire ça
Je trouve le décalage de bits plus facile que de taper 4,8,16,32 et ainsi de suite. Cela n'a aucun impact sur votre code car tout est fait au moment de la compilation
la source
Third = Second << 1
plutôt queThird = 1 << 2
- voir la description plus complète ci1 << 31 == -2147483648
,1 << 32 == 1
,1 << 33 == 2
et ainsi de suite. En revanche, si vous ditesThirtySecond = 2147483648
pour une énumération de type int, le compilateur génère une erreur.En combinant les réponses https://stackoverflow.com/a/8462/1037948 (déclaration par décalage de bits) et https://stackoverflow.com/a/9117/1037948 (en utilisant des combinaisons dans la déclaration), vous pouvez plutôt décaler les valeurs précédentes que d'utiliser des chiffres. Pas nécessairement le recommander, mais juste en soulignant que vous pouvez.
Plutôt que:
Vous pouvez déclarer
Confirmation avec LinqPad:
Résulte en:
la source
Veuillez consulter ce qui suit pour un exemple qui montre la déclaration et l'utilisation potentielle:
la source
En extension à la réponse acceptée, en C # 7 les drapeaux enum peuvent être écrits en utilisant des littéraux binaires:
Je pense que cette représentation montre clairement comment les drapeaux fonctionnent sous les couvertures .
la source
0b_0100
J'ai demandé récemment quelque chose de similaire.
Si vous utilisez des indicateurs, vous pouvez ajouter une méthode d'extension aux énumérations pour faciliter la vérification des indicateurs contenus (voir l'article pour plus de détails)
Cela vous permet de faire:
Ensuite, vous pouvez faire:
Je trouve cela plus facile à lire que la plupart des façons de vérifier les drapeaux inclus.
la source
HasFlag
méthode aux énumérations, vous pouvez donc vous passeropt.HasFlag( PossibleOptions.OptionOne )
de l'écriture de vos propres extensionsHasFlag
c'est beaucoup plus lent que d'effectuer des opérations au niveau du bit.@Nidonocu
Pour ajouter un autre indicateur à un ensemble de valeurs existant, utilisez l'opérateur d'affectation OU.
la source
Lorsque je travaille avec des drapeaux, je déclare souvent des éléments supplémentaires Aucun et Tous. Ces informations sont utiles pour vérifier si tous les indicateurs sont définis ou si aucun indicateur n'est défini.
Usage:
Mise à jour 2019-10:
Depuis C # 7.0, vous pouvez utiliser des littéraux binaires, qui sont probablement plus intuitifs à lire:
la source
Pour ajouter
Mode.Write
:la source
Il y a quelque chose de trop verbeux dans la
if ((x & y) == y)...
construction, surtout six
ETy
sont tous deux des ensembles composés de drapeaux et que vous voulez seulement savoir s'il y a un chevauchement.Dans ce cas, tout ce que vous devez vraiment savoir, c'est s'il y a une valeur non nulle [1] après avoir masqué le bit .
Construire à partir de la configuration de @ andnil ...
la source
enum
, nous devons vérifier!= 0
.Les indicateurs vous permettent d'utiliser le masquage de bit à l'intérieur de votre énumération. Cela vous permet de combiner les valeurs d'énumération, tout en conservant celles qui sont spécifiées.
la source
Toutes mes excuses si quelqu'un a déjà remarqué ce scénario. Un parfait exemple de drapeaux que nous pouvons voir en réflexion. Oui Binding Flags ENUM. https://docs.microsoft.com/en-us/dotnet/api/system.reflection.bindingflags?view=netframework-4.8
Usage
la source