165 votes

Pourquoi les autorisations enum ont-elles souvent des valeurs de 0, 1, 2, 4 ?

Pourquoi les gens utilisent-ils toujours des valeurs d'énumération comme 0, 1, 2, 4, 8 et non 0, 1, 2, 3, 4 ?

Cela a-t-il quelque chose à voir avec les opérations sur les bits, etc.

J'apprécierais vraiment un petit exemple d'utilisation correcte :)

[Flags]
public enum Permissions
{
    None   = 0,
    Read   = 1,
    Write  = 2,
    Delete = 4
}

272voto

Ed S. Points 70246

Parce que ce sont des puissances de deux et que je peux le faire :

var permissions = Permissions.Read | Permissions.Write;

Et peut-être plus tard...

if( (permissions & Permissions.Write) == Permissions.Write )
{
    // we have write access
}

Il s'agit d'un champ de bits, où chaque bit activé correspond à une permission (ou à ce à quoi la valeur énumérée correspond logiquement). Si elles étaient définies comme 1, 2, 3, ... vous ne seriez pas en mesure d'utiliser les opérateurs binaires de cette manière et d'obtenir des résultats significatifs. Pour aller plus loin...

Permissions.Read   == 1 == 00000001
Permissions.Write  == 2 == 00000010
Permissions.Delete == 4 == 00000100

Vous remarquez un modèle ici ? Maintenant, si nous reprenons mon exemple original, c'est-à-dire,

var permissions = Permissions.Read | Permissions.Write;

Alors...

permissions == 00000011

Tu vois ? Les deux Read y Write sont activés, et je peux le vérifier indépendamment (remarquez également que le fichier Delete est no et donc cette valeur ne donne pas l'autorisation de supprimer).

Il permet de stocker plusieurs drapeaux dans un seul champ de bits.

151voto

Eric Lippert Points 300275

Si les autres réponses ne sont toujours pas claires, pensez-y comme suit :

[Flags] 
public enum Permissions 
{   
   None = 0,   
   Read = 1,     
   Write = 2,   
   Delete = 4 
} 

est juste une façon plus courte d'écrire :

public enum Permissions 
{   
    DeleteNoWriteNoReadNo = 0,   // None
    DeleteNoWriteNoReadYes = 1,  // Read
    DeleteNoWriteYesReadNo = 2,  // Write
    DeleteNoWriteYesReadYes = 3, // Read + Write
    DeleteYesWriteNoReadNo = 4,   // Delete
    DeleteYesWriteNoReadYes = 5,  // Read + Delete
    DeleteYesWriteYesReadNo = 6,  // Write + Delete
    DeleteYesWriteYesReadYes = 7, // Read + Write + Delete
} 

Il y a huit possibilités mais vous pouvez les représenter comme des combinaisons de seulement quatre membres. S'il y avait seize possibilités, vous pourriez les représenter comme des combinaisons de seulement cinq membres. S'il y avait quatre milliards de possibilités, vous pourriez les représenter comme des combinaisons de seulement 33 membres ! Il est évidemment préférable de n'avoir que 33 membres, chacun (sauf zéro) étant une puissance de deux, que d'essayer de nommer quatre milliards d'éléments dans une énumération.

37voto

Chris Shain Points 33569

Parce que ces valeurs représentent des emplacements de bits uniques en binaire :

1 == binary 00000001
2 == binary 00000010
4 == binary 00000100

etc., donc

1 | 2 == binary 00000011

EDITAR:

3 == binary 00000011

Le 3 en binaire est représenté par une valeur de 1 à la fois à la place 1 et à la place 2. C'est en fait la même chose que la valeur 1 | 2 . Ainsi, lorsque vous essayez d'utiliser les positions binaires comme des drapeaux pour représenter un état, 3 n'est généralement pas significatif (à moins qu'il n'existe une valeur logique qui soit réellement la combinaison des deux).

Pour plus de clarté, vous pouvez étendre votre exemple d'enum comme suit :

[Flags]
public Enum Permissions
{
  None = 0,   // Binary 0000000
  Read = 1,   // Binary 0000001
  Write = 2,  // Binary 0000010
  Delete = 4, // Binary 0000100
  All = 7,    // Binary 0000111
}

C'est pourquoi j'ai Permissions.All j'ai aussi implicitement Permissions.Read , Permissions.Write y Permissions.Delete

11voto

Dozer Points 687
[Flags]
public Enum Permissions
{
    None   =    0; //0000000
    Read   =    1; //0000001
    Write  = 1<<1; //0000010
    Delete = 1<<2; //0000100
    Blah1  = 1<<3; //0001000
    Blah2  = 1<<4; //0010000
}

Je pense que ce type d'écriture est plus facile à comprendre et à lire, et qu'il n'est pas nécessaire de le calculer.

5voto

JaredPar Points 333733

Ils sont utilisés pour représenter les drapeaux binaires qui permettent de combiner les valeurs de l'enum. Je pense que c'est plus clair si vous écrivez les valeurs en notation hexadécimale

[Flags]
public Enum Permissions
{
  None =  0x00,
  Read =  0x01,
  Write = 0x02,
  Delete= 0x04,
  Blah1 = 0x08,
  Blah2 = 0x10
}

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