domingo, 12 de junio de 2011

Enumeraciones binarias

Las enumeraciones son un gran recurso que utilizo casi a diario en mis programas. De hecho, quizás las utilice en exceso, pero una vez me he acostumbrado a trabajar con ellas, lo cierto es que ya no puedo vivir sin ellas.

Un aspecto de las enumeraciones que no es muy utilizado pero que reporta grandes beneficios son las denominadas “enumeraciones binarias”. Por ejemplo, piensa que tenemos una enumeración “Persona” que tiene los siguientes valores: Alto, Bajo, Rubio, Moreno, Delgado, Gordo, Inteligente y Tonto. Todo el mundo sabe cómo asignar un valor sencillo de la enumeración a una variable, por ejemplo:

    Public Enum Persona As Integer

        Alto

        Bajo

        Rubio

        Moreno

        Delgado

        Gordo

        Inteligente

        Tonto

    End Enum

 

    Sub Main()

        Dim manolo As Persona = Persona.Alto

        If manolo = Persona.Alto Then

            Console.WriteLine("Manolo es alto")

        End If

    End Sub

 

Sin embargo ¿Cómo podemos guardar en la misma variable que Manolo, además de Alto también es Rubio y Delgado? Para resolver esto tenemos que utilizan enumeraciones binarias.

Definición

Una enumeración binaria tiene que cumplir las siguientes características:

·         El primer valor de la enumeración tiene que ser 1 (no 0, como es por defecto).

·         El resto de valores de la enumeración tienen que ser la potencia de 2.

·         Tenemos que incluir el adorno Flags.

De este modo, la anterior enumeración quedaría como sigue:

    <Flags()> _

    Public Enum Persona As Integer

        Alto = 1

        Bajo = 2

        Rubio = 4

        Moreno = 8

        Delgado = 32

        Gordo = 64

    End Enum

 

A partir de aquí tenemos que trabajar con operadores lógicos para asignar, consultar o retirar valores de una variable del tipo “Persona”. Los operadores disponibles son:

·         And, conjunción lógica.

·         Or, disyunción lógica.

·         Not, negación lógica.

·         Xor, exclusión lógica.

Agregar valores

Se agregan (suman) valores con el operador Or.

Dim manolo As Persona

manolo = Persona.Alto ' Manolo sólo es Alto (1)

manolo = Persona.Alto Or Persona.Rubio 'Manolo es Alto y Rubio. (5)

manolo = manolo Or Persona.Delgado 'Manolo es además de Alto y Rubio, también Delgado. (37)

 

Si nos fijamos, la primera asignación asigna el valor 1 (Alto) a la variable Manolo.

La segunda asignación asigna el valor 1 (Alto) y el valor 4 (Rubio) a la variable Manolo. De ese modo, Manolo vale 5 (la suma de Alto y Rubio).

Por último, la tercera asignación asigna el valor que ya tuviera Manolo (que podría ser cualquiera pero en nuestro caso es 4 – Alto y Rubio) más el valor 35 (Delgado). Finalmente, Manolo vale 37 (la suma de Alto y Rubio y Delgado).

En lo relativo a la suma de valores, da igual que sumemos varias veces un valor, no por ello Manolo será 2 veces alto!

Retirar valores

Se retiran (restan) valores con el operador Xor.

manolo = Persona.Alto Or Persona.Rubio

manolo = manolo Xor Persona.Rubio 'Manolo ya NO es Rubio (1)

 

Ahora, Manolo ya es no Rubio y su valor es 1, luego es Alto.

Con la resta de valores (Xor) hay que tener mucho cuidado, ya que si intenta restar un valor que actualmente no está asignado, en vez de restar lo que hará es sumar el valor. Por ejemplo:

manolo = Persona.Alto Or Persona.Rubio

manolo = manolo Xor Persona.Rubio 'Manolo ya NO es Rubio (1)

' Manolo no es Moreno, pero intentamos retirar (Xor) el valor Moreno, y en vez de retirarlo lo que hacemos es agregarlo

manolo = manolo Xor Persona.Moreno 'Ahora Manolo es Alto y Moreno (9)

 

Para resolver esto, antes de retirar (restar) un valor hay que asegurarse de que el valor existe realmente. Por ejemplo:

manolo = Persona.Alto Or Persona.Rubio

' Sólo si Manolo es Moreno, le retiramos (restamos) Manolo

If manolo And Persona.Rubio Then 'Comprobar si Manolo es Moreno

manolo = manolo Xor Persona.Moreno

End If

 

Consultar valores

Para consultar valores podemos llevar a cabo las siguientes instrucciones:

manolo = Persona.Bajo Or Persona.Moreno

If manolo = Persona.Bajo Then

Console.WriteLine("Manolo es SÓLO Bajo, nada más")

End If

If manolo And Persona.Bajo Then

Console.WriteLine("Manolo es Bajo")

End If

If manolo = (Persona.Bajo Or Persona.Moreno) Then

Console.WriteLine("Manolo es Bajo y Moreno")

End If

 

Un saludo!.

1 comentario:

  1. Me ha hecho acordar a los Flags del CommonDialog del viejo VB6, funcionan exactamente de la misma manera. Gracias por el post, ahora ya sé cómo implementar estos Flags :D

    ResponderEliminar