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

unity - ¿Qué significa el atributo Enum de[Flags] en C#?



enum multiple values c# (11)

@Nidonocu

Para agregar otra bandera a un conjunto de valores existente, use el operador de asignación OR.

Mode = Mode.Read; //Add Mode.Write Mode |= Mode.Write; Assert.True(((Mode & Mode.Write) == Mode.Write) && ((Mode & Mode.Read) == Mode.Read)));

De vez en cuando veo una enumeración como la siguiente:

[Flags] public enum Options { None = 0, Option1 = 1, Option2 = 2, Option3 = 4, Option4 = 8 }

No entiendo qué hace exactamente el atributo [Flags] .

¿Alguien tiene una buena explicación o ejemplo que puedan publicar?


Combinando respuestas https://.com/a/8462/1037948 (declaración mediante cambio de bits) y https://.com/a/9117/1037948 (utilizando combinaciones en la declaración) puede cambiar los valores anteriores en lugar de que usar números No necesariamente lo recomiendo, pero solo señalando que puedes.

Más bien 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, }

Puedes declarar

[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, }

Confirmando con LinqPad:

foreach(var e in Enum.GetValues(typeof(Options))) { string.Format("{0} = {1}", e.ToString(), (byte)e).Dump(); }

Resultados en:

None = 0 One = 1 Two = 2 OneAndTwo = 3 Three = 4 OneTwoAndThree = 7 Four = 8


Consulte lo siguiente para ver un ejemplo que muestra la declaración y el uso potencial:

namespace Flags { class Program { [Flags] 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"); } } } }


Cuando trabajo con banderas a menudo declaro Ninguno y Todos los elementos adicionales. Estos son útiles para verificar si todos los indicadores están establecidos o si no hay ningún indicador establecido.

[Flags] enum SuitsFlags { None = 0, Spades = 1 << 0, Clubs = 1 << 1, Diamonds = 1 << 2, Hearts = 1 << 3, All = ~(~0 << 4) }

Uso:

Spades | Clubs | Diamonds | Hearts == All // true Spades & Clubs == None // true


El atributo flags debe usarse siempre que el enumerable represente una colección de flags, en lugar de un solo valor. Dichas colecciones se suelen manipular utilizando operadores bitwise, por ejemplo:

myProperties.AllowedColors = MyColor.Red | MyColor.Green | MyColor.Blue;

Tenga en cuenta que [Flags] por sí mismos no cambian esto en absoluto , todo lo que hace es habilitar una buena representación mediante el método .ToString() :

enum Suits { Spades = 1, Clubs = 2, Diamonds = 4, Hearts = 8 } [Flags] enum SuitsFlags { 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"

También es importante tener en cuenta que [Flags] no hace automáticamente que los valores de enumeración sean potencias de dos. Si omite los valores numéricos, la enumeración no funcionará como cabría esperar en las operaciones a nivel de bits, ya que, de forma predeterminada, los valores comienzan con 0 e incrementan.

Declaración incorrecta:

[Flags] public enum MyColors { Yellow, Green, Red, Blue }

Los valores, si se declaran de esta manera, serán Amarillo = 0, Verde = 1, Rojo = 2, Azul = 3. Esto lo hará inútil para su uso como indicadores.

Aquí hay un ejemplo de una declaración correcta:

[Flags] public enum MyColors { Yellow = 1, Green = 2, Red = 4, Blue = 8 }

Para recuperar los valores distintos en su propiedad, uno puede hacer esto:

if((myProperties.AllowedColors & MyColor.Yellow) == MyColor.Yellow) { // Yellow has been set... } if((myProperties.AllowedColors & MyColor.Green) == MyColor.Green) { // Green has been set... }

o, en .NET 4 y posteriores:

if (myProperties.AllowedColors.HasFlag(MyColor.Yellow)) { // Yellow has been set... }

Debajo de las sábanas

Esto funciona porque anteriormente usaste poderes de dos en tu enumeración. Bajo las cubiertas, sus valores de enumeración se ven así (presentados como bytes, que tienen 8 bits que pueden ser 1 o 0)

Yellow: 00000001 Green: 00000010 Red: 00000100 Blue: 00001000

Del mismo modo, una vez que haya configurado su propiedad AllowedColors en rojo, verde y azul (cuyos valores fueron OR por el pipe |), AllowedColors se verá así

myProperties.AllowedColors: 00001110

Por lo tanto, cuando recuperas el valor, realmente estás en modo de bit y se están ajustando los valores.

myProperties.AllowedColors: 00001110 MyColor.Green: 00000010 ----------------------- 00000010 // Hey, this is the same as MyColor.Green!

El valor de Ninguno = 0

Y con respecto al uso 0 en tu enumeración, citando de msdn:

[Flags] public enum MyColors { None = 0, .... }

Utilice Ninguno como el nombre de la constante enumerada de la bandera cuyo valor es cero. No puede usar la constante enumerada Ninguna en una operación AND a nivel de bits para probar un indicador porque el resultado siempre es cero. Sin embargo, puede realizar una comparación lógica, no a nivel de bits, entre el valor numérico y la constante enumerada Ninguna para determinar si se establece algún bit en el valor numérico.

Puede encontrar más información sobre el atributo flags y su uso en msdn y diseño de flags en msdn


En extensión a la respuesta aceptada, en C # 7, las marcas de enumeración se pueden escribir utilizando literales binarios:

[Flags] public enum MyColors { None = 0b0000, Yellow = 0b0001, Green = 0b0010, Red = 0b0100, Blue = 0b1000 }

Creo que esta representación deja claro cómo funcionan las banderas debajo de las cubiertas .


Hay algo demasiado detallado para mí sobre el constructo if ((x & y) == y)... especialmente, si x AND y son conjuntos compuestos de banderas y solo quieres saber si hay alguna superposición.

En este caso, todo lo que realmente necesita saber es si hay un valor distinto de cero [1] después de haber enmascarado .

[1] Ver el comentario de Jaime. Si estuviéramos enmascarados de forma auténtica, solo tendríamos que comprobar que el resultado fue positivo. Pero como las enum pueden ser negativas, incluso, de forma extraña, cuando se combinan con msdn , es defensivo codificar para != 0 lugar de > 0 .

Construyendo a partir de la configuración de @nnnil ...

using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace BitFlagPlay { class Program { [Flags] public enum MyColor { Yellow = 0x01, Green = 0x02, Red = 0x04, Blue = 0x08 } static void Main(string[] args) { var myColor = MyColor.Yellow | MyColor.Blue; var acceptableColors = MyColor.Yellow | MyColor.Red; Console.WriteLine((myColor & MyColor.Blue) != 0); // True Console.WriteLine((myColor & MyColor.Red) != 0); // False Console.WriteLine((myColor & acceptableColors) != 0); // True // ... though only Yellow is shared. Console.WriteLine((myColor & MyColor.Green) != 0); // Wait a minute... ;^D Console.Read(); } } }


Las banderas le permiten usar máscaras de bits dentro de su enumeración. Esto le permite combinar valores de enumeración, mientras retiene los que están especificados.

[Flags] public enum DashboardItemPresentationProperties : long { None = 0, HideCollapse = 1, HideDelete = 2, HideEdit = 4, HideOpenInNewWindow = 8, HideResetSource = 16, HideMenu = 32 }


Le pregunté recientemente sobre algo similar.

Si usa marcas, puede agregar un método de extensión a las enumeraciones para facilitar la comprobación de las marcas contenidas (consulte la publicación para obtener más detalles)

Esto te permite hacer:

[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, ... }

Entonces puedes hacer:

PossibleOptions opt = PossibleOptions.OptionOneTwoAndThree if( opt.IsSet( PossibleOptions.OptionOne ) ) { //optionOne is one of those set }

Encuentro esto más fácil de leer que la mayoría de las formas de verificar las banderas incluidas.


Para añadir Mode.Write :

Mode = Mode | Mode.Write;


También puedes hacer esto

[Flags] public enum MyEnum { None = 0, First = 1 << 0, Second = 1 << 1, Third = 1 << 2, Fourth = 1 << 3 }

Encuentro el cambio de bits más fácil que escribir 4,8,16,32 y así sucesivamente. No tiene ningún impacto en su código porque todo se hace en tiempo de compilación