Quelqu'un a-t-il une bonne explication ou un exemple qu'il pourrait poster ?
Edit : J'ai changé la réponse, celle-ci est plus approfondie.
Quelqu'un a-t-il une bonne explication ou un exemple qu'il pourrait poster ?
Edit : J'ai changé la réponse, celle-ci est plus approfondie.
L'attribut flags doit être utilisé lorsque l'énumérable représente une collection de drapeaux, plutôt qu'une valeur unique. Ces collections sont généralement manipulées à l'aide d'opérateurs binaires, par exemple :
myProperties.AllowedColors = MyColor.Red | MyColor.Green | MyColor.Blue;
Notez que [Flags]
en soi ne change rien du tout - tout ce qu'il fait, c'est permettre une belle représentation par le .ToString()
méthode :
[Flags] enum SuitsFlags { Spades = 1, Clubs = 2, Diamonds = 4, Hearts = 8 }
enum Suits { Spades = 1, Clubs = 2, Diamonds = 4, Hearts = 8 }
...
var str1 = (Suits.Spades | Suits.Diamonds).ToString();
// "5"
var str2 = (SuitsFlags.Spades | SuitsFlags.Diamonds).ToString();
// "Spades, Diamonds"
Il est également important de noter que [Flags]
n'est pas rend automatiquement les valeurs de l'énumération des puissances de deux. Si vous omettez les valeurs numériques, l'énumération ne fonctionnera pas comme on pourrait s'y attendre dans les opérations de type bitwise, car par défaut les valeurs commencent par 0 et s'incrémentent.
Déclaration incorrecte :
[Flags]
public enum MyColors
{
Yellow,
Green,
Red,
Blue
}
Les valeurs, si elles sont déclarées de cette façon, seront Jaune = 0, Vert = 1, Rouge = 2, Bleu = 3. Cela les rendra inutilisables en tant que drapeaux.
Voici un exemple de déclaration correcte :
[Flags]
public enum MyColors
{
Yellow = 1,
Green = 2,
Red = 4,
Blue = 8
}
Pour récupérer les valeurs distinctes dans votre propriété, on peut faire ceci
if((myProperties.AllowedColors & MyColor.Yellow) == MyColor.Yellow)
{
// Yellow has been set...
}
if((myProperties.AllowedColors & MyColor.Green) == MyColor.Green)
{
// Green has been set...
}
ou, dans .NET 4 et plus,
if (myProperties.AllowedColors.HasFlag(MyColor.Yellow))
{
// Yellow has been set...
}
Sous les couvertures
Cela fonctionne parce que vous avez précédemment utilisé des multiples de deux dans votre énumération. En réalité, les valeurs de votre énumération ressemblent à ceci (présentées sous forme d'octets, qui ont 8 bits qui peuvent être des 1 ou des 0)
Yellow: 00000001
Green: 00000010
Red: 00000100
Blue: 00001000
De même, après avoir défini votre propriété Couleurs autorisées à Rouge, Vert et Bleu (ces valeurs sont mises sous OR par le pipe |), Couleurs autorisées ressemble à ceci
myProperties.AllowedColors: 00001110
Donc, lorsque vous récupérez la valeur, vous êtes en fait en train de faire un ET binaire des valeurs.
myProperties.AllowedColors: 00001110
MyColor.Green: 00000010
-----------------------
00000010 // Hey, this is the same as MyColor.Green!
La valeur None = 0
Et concernant l'utilisation de 0 dans votre énumération, je cite le msdn :
[Flags]
public enum MyColors
{
None = 0,
....
}
Utilisez None comme nom de la constante énumérée du drapeau dont la valeur est zéro. Vous ne pouvez pas utiliser la constante énumérée None dans une opération ET par bit pour tester un indicateur car le résultat est toujours zéro. Toutefois, vous pouvez effectuer une comparaison logique, et non bit à bit, entre la valeur numérique et la constante énumérée None pour déterminer si l'un des bits de la valeur numérique est activé.
Vous trouverez de plus amples informations sur l'attribut flags et son utilisation à l'adresse suivante msdn y conception de drapeaux à msdn
Vous pouvez également le faire
[Flags]
public enum MyEnum
{
None = 0,
First = 1 << 0,
Second = 1 << 1,
Third = 1 << 2,
Fourth = 1 << 3
}
Je trouve le décalage des 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.
Combiner les réponses http://stackoverflow.com/a/8462/1037948 (déclaration par décalage de bits) et http://stackoverflow.com/a/9117/1037948 (en utilisant des combinaisons dans la déclaration) vous pouvez décaler les valeurs précédentes en bits plutôt que d'utiliser des chiffres. Je ne le recommande pas nécessairement, mais je signale simplement que c'est possible.
Plutôt que :
[Flags]
public enum Options : byte
{
None = 0,
One = 1 << 0, // 1
Two = 1 << 1, // 2
Three = 1 << 2, // 4
Four = 1 << 3, // 8
// combinations
OneAndTwo = One | Two,
OneTwoAndThree = One | Two | Three,
}
Vous pouvez déclarer
[Flags]
public enum Options : byte
{
None = 0,
One = 1 << 0, // 1
// now that value 1 is available, start shifting from there
Two = One << 1, // 2
Three = Two << 1, // 4
Four = Three << 1, // 8
// same combinations
OneAndTwo = One | Two,
OneTwoAndThree = One | Two | Three,
}
Confirmation avec LinqPad :
foreach(var e in Enum.GetValues(typeof(Options))) {
string.Format("{0} = {1}", e.ToString(), (byte)e).Dump();
}
Résultats dans :
None = 0
One = 1
Two = 2
OneAndTwo = 3
Three = 4
OneTwoAndThree = 7
Four = 8
Veuillez consulter l'exemple suivant qui illustre la déclaration et l'utilisation potentielle :
namespace Flags
{
class Program
{
[FlagsAttribute]
public enum MyFlags : short
{
Foo = 0x1,
Bar = 0x2,
Baz = 0x4
}
static void Main(string[] args)
{
MyFlags fooBar = MyFlags.Foo | MyFlags.Bar;
if ((fooBar & MyFlags.Foo) == MyFlags.Foo)
{
Console.WriteLine("Item has Foo flag set");
}
}
}
}
I a demandé récemment à propos de quelque chose de similaire.
Si vous utilisez des drapeaux, vous pouvez ajouter une méthode d'extension aux enums pour faciliter la vérification des drapeaux contenus (voir le post pour plus de détails).
Cela vous permet de faire :
[Flags]
public enum PossibleOptions : byte
{
None = 0,
OptionOne = 1,
OptionTwo = 2,
OptionThree = 4,
OptionFour = 8,
//combinations can be in the enum too
OptionOneAndTwo = OptionOne | OptionTwo,
OptionOneTwoAndThree = OptionOne | OptionTwo | OptionThree,
...
}
Alors vous pouvez le faire :
PossibleOptions opt = PossibleOptions.OptionOneTwoAndThree
if( opt.IsSet( PossibleOptions.OptionOne ) ) {
//optionOne is one of those set
}
Je trouve cela plus facile à lire que la plupart des façons de vérifier les drapeaux inclus.
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.