variable values unity multiple español enum bitwise c# enums flags

unity - enum multiple values c#



¿Por qué usar flags+bitmasks en lugar de una serie de booleanos? (10)

  1. Eficiencia de espacio - 1 bit
  2. Eficiencia en el tiempo: las comparaciones de bits se manejan rápidamente mediante hardware.
  3. Independencia del idioma: donde los datos pueden ser manejados por una serie de programas diferentes, no necesita preocuparse por la implementación de los booleanos en diferentes idiomas / plataformas.

La mayoría de las veces, estos no valen la compensación en términos de mantenimiento. Sin embargo, hay ocasiones en que es útil:

  1. Protocolos de red: habrá un gran ahorro en el tamaño reducido de los mensajes.
  2. Software heredado: una vez tuve que agregar información para rastrearlo en algún software heredado.

Costo para modificar el encabezado: millones de dólares y años de esfuerzo. Costo de calzar la información en 2 bytes en el encabezado que no se estaba utilizando: 0.

Por supuesto, hubo un costo adicional en el código que accedió a esta información y la manipuló, pero de todos modos, esto se realizó mediante funciones, por lo que una vez que se definieron los accesores, no era menos fácil de mantener que usar Booleans.

En un caso en el que tengo un objeto que puede estar en uno o más estados de verdadero / falso, siempre he estado un poco confuso sobre por qué los programadores usan con frecuencia banderas + máscaras de bits en lugar de solo usar varios valores booleanos.

Está todo en el marco de .NET. No estoy seguro de si este es el mejor ejemplo, pero el marco .NET tiene lo siguiente:

public enum AnchorStyles { None = 0, Top = 1, Bottom = 2, Left = 4, Right = 8 }

Por lo tanto, dado un estilo de anclaje, podemos usar máscaras de bits para determinar cuáles de los estados están seleccionados. Sin embargo, parece que podría lograr lo mismo con una clase / estructura AnchorStyle con propiedades bool definidas para cada valor posible, o una matriz de valores de enumeración individuales.

Por supuesto, la razón principal de mi pregunta es que me pregunto si debo seguir una práctica similar con mi propio código.

Entonces, ¿por qué utilizar este enfoque?

  • ¿Menos consumo de memoria? (No parece que consumiría menos que una matriz / estructura de bools)
  • ¿Mejor rendimiento de pila / pila que una estructura o matriz?
  • ¿Operaciones de comparación más rápidas? ¿Adición / eliminación de valor más rápido?
  • ¿Más conveniente para el desarrollador que lo escribió?

Desde la perspectiva del Modelo de dominio, simplemente modela mejor la realidad en algunas situaciones. Si tiene tres valores booleanos como AccountIsInDefault e IsPreferredCustomer y RequiereSalesTaxState, entonces no tiene sentido agregarlos a una sola enumeración decorada de Flags, ya que no son tres valores distintos para el mismo elemento de modelo de dominio.

Pero si tienes un conjunto de booleanos como:

[Flags] enum AccountStatus {AccountIsInDefault=1, AccountOverdue=2 and AccountFrozen=4}

o

[Flags] enum CargoState {ExceedsWeightLimit=1, ContainsDangerousCargo=2, IsFlammableCargo=4, ContainsRadioactive=8}

Entonces es útil poder almacenar el estado total de la cuenta (o la carga) en UNA variable ... que representa UN elemento de dominio cuyo valor puede representar cualquier combinación posible de estados.


En realidad, puede tener un mejor rendimiento, principalmente si su enumeración se deriva de un byte. En ese caso extremo, cada valor de enumeración estaría representado por un byte, que contiene todas las combinaciones, hasta 256. Tener tantas combinaciones posibles con booleanos llevaría a 256 bytes.

Pero, incluso entonces, no creo que esa sea la verdadera razón. La razón por la que prefiero esos es el poder que C # me da para manejar esos enumerados. Puedo agregar varios valores con una sola expresión. Puedo eliminarlos también. Incluso puedo comparar varios valores a la vez con una sola expresión utilizando la enumeración. Con los booleanos, el código puede volverse, digamos, más detallado.


Entre otras cosas, es más fácil agregar nuevos significados de bits a un campo de bits que agregar nuevos valores booleanos a una clase. También es más fácil copiar un campo de bits de una instancia a otra que una serie de valores booleanos.


Era tradicionalmente una forma de reducir el uso de la memoria. Entonces, sí, es bastante obsoleto en C # :-)

Como técnica de programación, puede que esté obsoleto en los sistemas actuales, y sería muy bueno usar una serie de bools, pero ...

Es rápido comparar valores almacenados como una máscara de bits. Use los operadores lógicos AND y OR y compare los 2 ints resultantes.

Utiliza considerablemente menos memoria. Poner los 4 valores de ejemplo en una máscara de bits usaría medio byte. Usando una matriz de bools, lo más probable es que use unos pocos bytes para el objeto de la matriz más una palabra larga para cada bools. Si tiene que almacenar un millón de valores, verá exactamente por qué una versión de máscara de bits es superior.

Es más fácil de administrar, solo tiene que lidiar con un solo valor entero, mientras que una matriz de bools se almacenaría de manera muy diferente en, digamos, una base de datos.

Y, debido al diseño de la memoria, es mucho más rápido en todos los aspectos que en una matriz. Es casi tan rápido como usar un solo entero de 32 bits. Todos sabemos que es lo más rápido que puede obtener para operaciones sobre datos.


Es por velocidad y eficiencia. Esencialmente, todo con lo que estás trabajando es un solo int.

if ((flags & AnchorStyles.Top) == AnchorStyles.Top) { //Do stuff }


Raymond Chen tiene una publicación de blog sobre este tema .

Claro, los campos de bits guardan la memoria de datos, pero hay que equilibrarla con el costo en tamaño de código, capacidad de depuración y reducción de subprocesos múltiples.

Como han dicho otros, su tiempo es en gran parte pasado. Es tentador seguir haciéndolo, porque la manipulación de los bits es divertida y atractiva, pero ya no es más eficiente, tiene serios inconvenientes en términos de mantenimiento, no funciona bien con las bases de datos y, a menos que esté trabajando en una Mundo incrustado, tienes suficiente memoria.


También puede hacer que los métodos sean más claros. Imagina un método con 10 bools vs. 1 Bitmask.


Yo sugeriría nunca usar indicadores de enumeración a menos que esté lidiando con algunas limitaciones de memoria bastante serias (no es probable). Siempre debe escribir código optimizado para el mantenimiento.

Tener varias propiedades booleanas hace que sea más fácil leer y entender el código, cambiar los valores y proporcionar comentarios de Intellisense, por no mencionar que reduce la probabilidad de errores. Si es necesario, siempre puede usar un campo de indicador de enumeración internamente, solo asegúrese de exponer la configuración / obtención de los valores con propiedades booleanas.


  • Fácil configuración de múltiples banderas en cualquier orden.

  • Fácil de guardar y obtener una serie de 0101011 a la base de datos.