c# - español - enum net core
¿Por qué los permisos enum a menudo tienen 0, 1, 2, 4 valores? (7)
¿Por qué las personas siempre usan valores enum como 0, 1, 2, 4, 8
y no 0, 1, 2, 3, 4
?
Tiene esto algo que ver con las operaciones de bits, etc.?
Realmente apreciaría un pequeño fragmento de muestra sobre cómo se usa esto correctamente :)
[Flags]
public enum Permissions
{
None = 0,
Read = 1,
Write = 2,
Delete = 4
}
Debido a que estos valores representan ubicaciones de bits únicas en binario:
1 == binary 00000001
2 == binary 00000010
4 == binary 00000100
etc., entonces
1 | 2 == binary 00000011
EDITAR:
3 == binary 00000011
3 en binario está representado por un valor de 1 tanto en el lugar de las unidades como en el de dos. En realidad es lo mismo que el valor 1 | 2
1 | 2
. Entonces, cuando intenta usar los lugares binarios como banderas para representar algún estado, 3 generalmente no tiene sentido (a menos que haya un valor lógico que realmente sea la combinación de los dos)
Para mayor aclaración, es posible que desee extender su enumeración de ejemplo de la siguiente manera:
[Flags]
public Enum Permissions
{
None = 0, // Binary 0000000
Read = 1, // Binary 0000001
Write = 2, // Binary 0000010
Delete = 4, // Binary 0000100
All = 7, // Binary 0000111
}
Por lo tanto, en Tengo Permissions.All
, también implícitamente tengo Permissions.Read
, Permissions.Write
y Permissions.Delete
Esto es realmente más un comentario, pero como eso no sería compatible con el formato, solo quería incluir un método que he empleado para configurar las enumeraciones de banderas:
[Flags]
public enum FlagTest
{
None = 0,
Read = 1,
Write = Read * 2,
Delete = Write * 2,
ReadWrite = Read|Write
}
Encuentro este enfoque especialmente útil durante el desarrollo en el caso en el que desea mantener sus banderas en orden alfabético. Si determina que necesita agregar un nuevo valor de indicador, puede simplemente insertarlo alfabéticamente y el único valor que tiene que cambiar es el que ahora precede.
Sin embargo, tenga en cuenta que una vez que se publica una solución en cualquier sistema de producción (especialmente si la enumeración está expuesta sin un acoplamiento ajustado, como en un servicio web), es muy recomendable no modificar ningún valor existente dentro de la enumeración.
Estos se usan para representar banderas de bits que permiten combinaciones de valores enum. Creo que es más claro si escribes los valores en notación hexadecimal
[Flags]
public Enum Permissions
{
None = 0x00,
Read = 0x01,
Write = 0x02,
Delete= 0x04,
Blah1 = 0x08,
Blah2 = 0x10
}
Hay muchas buenas respuestas para esto ... Solo diré ... si no te gusta, o no puedes entender fácilmente lo que la sintaxis <<
está tratando de expresar ... Personalmente prefiero una alternativa (y me atrevo a decir, declaración enum directa) estilo)…
typedef NS_OPTIONS(NSUInteger, Align) {
AlignLeft = 00000001,
AlignRight = 00000010,
AlignTop = 00000100,
AlignBottom = 00001000,
AlignTopLeft = 00000101,
AlignTopRight = 00000110,
AlignBottomLeft = 00001001,
AlignBottomRight = 00001010
};
NSLog(@"%ld == %ld", AlignLeft | AlignBottom, AlignBottomLeft);
LOG 513 == 513
Mucho más fácil (para mí, al menos) comprender. Alinee los que ... describa el resultado que desea, obtenga el resultado que DESEA. No es necesario hacer "cálculos".
Porque son poderes de dos y puedo hacer esto:
var permissions = Permissions.Read | Permissions.Write;
Y quizás más tarde ...
if( (permissions & Permissions.Write) == Permissions.Write )
{
// we have write access
}
Es un campo de bit, donde cada bit configurado corresponde a algún permiso (o lo que corresponde lógicamente al valor enumerado). Si se definieran como 1, 2, 3, ...
no sería posible usar operadores bit a bit de esta manera y obtener resultados significativos. Para profundizar más ...
Permissions.Read == 1 == 00000001
Permissions.Write == 2 == 00000010
Permissions.Delete == 4 == 00000100
Observe un patrón aquí? Ahora, si tomamos mi ejemplo original, es decir,
var permissions = Permissions.Read | Permissions.Write;
Entonces...
permissions == 00000011
¿Ver? Los bits de Read
y Write
están configurados, y puedo verificarlo de forma independiente (también observe que el bit de Delete
no está configurado y, por lo tanto, este valor no transmite permiso para eliminar).
Le permite a uno almacenar múltiples banderas en un solo campo de bits.
Si aún no está claro de las otras respuestas, piénsalo de esta manera:
[Flags]
public enum Permissions
{
None = 0,
Read = 1,
Write = 2,
Delete = 4
}
es solo una forma más corta de escribir:
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
}
Hay ocho posibilidades, pero puede representarlas como combinaciones de solo cuatro miembros. Si hubiera dieciséis posibilidades, podría representarlas como combinaciones de solo cinco miembros. Si hubiera cuatro mil millones de posibilidades, ¡podría representarlas como combinaciones de solo 33 miembros! Obviamente, es mucho mejor tener solo 33 miembros, cada uno (excepto cero) una potencia de dos, que tratar de nombrar cuatro mil millones de elementos en una enumeración.
[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
}
Creo que escribir así es más fácil de entender y leer, y no es necesario calcularlo.