Mostrando entradas con la etiqueta Chapter03. Mostrar todas las entradas
Mostrando entradas con la etiqueta Chapter03. Mostrar todas las entradas

jueves, 15 de mayo de 2014

Enumeraciones en C# - Parte 4

Tabla de Contenido

0. Introducción
1. Operadores de Igualdad y Asignación
2. Operadores de Comparación
3. Operadores Aritméticos
4. Operadores Bitwise
5. Operador sizeof
6. Notas Importantes
7. Conclusiones
8. Glosario
9. Literatura & Enlaces

0. Introducción

En esta cuarta parte de la serie de Enumeraciones en C#, ha llegado el momento de tratar con el funcionamiento de los operadores permitidos para las enumeraciones. Incluiré la demostración de varios de los operadores disponibles para manipular los valores de una constante de una enumeración; igualmente, presentaré las restricciones impuestas sobre los operadores al manipular dos o más constantes de una enumeración. Incluiré, además, ejemplos concretos para comprender a fondo el uso de los operadores: =, ==, !=, <, >, <=, >=, +, -, ^, &, |, ~, +=, -=, ++, --, sizeof.

Artículos de la serie:

Parte 1 - Introducción a la enumeraciones en C#
Parte 2 - Operaciones de las enumeraciones
Parte 3 - Valores bandera de las enumeraciones
Parte 4 - Operadores de las enumeraciones
Parte 5 - Casos de seguridad de tipos

1. Operadores de Igualdad y Asignación

Los operadores de igualdad permitidos para las enumeración son los siguientes:
  • == : Determina si dos constantes de una enumeración contienen el mismo valor.
  • != : Determina si dos constantes (miembros) de una enumeración contienen valores diferentes.
Veamos estos ejemplos de uso:

if ((derechoIzquierdo & Bordes.Derecho) != 0)

En esta línea de código se realiza la operación bitwise AND para determinar si la variable derechoIzquierdo (Bordes) contiene el valor Bordes.Derecho. Finalmente se determina a través del operador de igualdad, !=, si el resultado de la operación AND es diferente de cero.

El operador de igualdad, == (leído: igual-igual) se usa de la siguiente manera:

if ((borde & Bordes.Derecho) == 1)


Esta línea determina si la variable borde al operarla con Borde.Derecho a través de la operación bitwise AND (&), poseen los mismos valores.

[Nota: Más acerca de estos operadores en [3].]

2. Operadores de Comparación

Este es el conjunto de los operadores permitidos para una enumeración:
  • < : (Menor que) 
  • > : (Mayor que)
  • <= : (Menor o igual a)
  • >= : (Mayor o igual a)
Veamos ejemplos de cada uno:

Menor que (<):

Console.WriteLine(Dias.Jueves < Dias.Miercoles); // Salida: False

Mayor que (>):

Console.WriteLine(Dias.Martes > Dias.Lunes); // Salida: True

Menor o igual a (<=):

Dias martes = Dias.Martes;
Console.WriteLine(Dias.Miercoles >= martes); // Salida: True

Mayor o igual a (>=):

Console.WriteLine(Dias.Viernes <= Dias.Jueves); // Salida: False

3. Operadores Aritméticos

Antes de entrar en detalles acerca de las operaciones aritméticas permitidas sobre las enumeraciones, vale aclarar que la adición sólo está permitida entre un miembro (constante) de la enumeración y un valor entero concreto. Inclusive, intentar sumar dos constantes la enumeración generará un error [1].

Veamos lo que ocurre al intentar sumar dos constantes:

Dias lunes = Dias.Lunes;
Dias miercoles = Dias.Miercoles;

Console.WriteLine(lunes + miercoles);

La última línea generará el error CS0019 [5]:

error CS0019: Operator `+' cannot be applied to operands of type `Dias' and `Dias'


Mientras que:

La suma y la resta se realizan de esta manera:

Dias lunes = Dias.Lunes;
Dias miercoles = Dias.Miercoles;

Dias suma = lunes + (1 << 1);
Console.WriteLine("Suma de `lunes` y `(1 << 1)`: {0}", suma.ToString("F"));

Dias resta = miercoles - (1 << 2);
Console.WriteLine("Resta de `miercoles` y (1 << 2)`: {0}", resta.ToString("F"));


Resultado:
Suma de `lunes` y `(1 << 1)`: Martes
Resta de `miercoles` y (1 << 2)`: Martes

4. Operadores Bitwise

[Nota: En la sección 2 (Banderas en Enumeraciones) se explican los operadores | (OR inclusivo), & (AND), y ^ (OR exclusivo) de la parte 3 acerca de Enumeraciones en C#: Enumeraciones en C# - Parte 3.]

5. Operador sizeof de una Enumeración

Podemos usar el operador sizeof [6] para obtener el espacio ocupado en memoria por una enumeración. Por ejemplo:

int tamanioEnum = sizeof(Dias);

Console.WriteLine("El tamaño de la enumeración `Dias` es {0} bytes", tamanioEnum);


Resultado:
El tamaño de la enumeración `Dias` es 4 bytes

6. Notas Importantes

Recomiendo la lectura de otro de mis artículos donde se describe con más nivel de detalle el uso de los operadores bitwise:

Enlace: Operadores Bitwise (Bit a Bit) en C#.

Por otro lado, en [1] nos advierten de:
The bitwise, arithmetic, and comparison operators return the result of processing the underlying integral values.

7. Conclusiones

Hemos aprendido a usar varios de los operadores aplicables a enumeraciones. Vimos el uso de los operadores de igualdad, de comparación, aritméticos, bit-a-bit (bitwise). Al final practicamos, grosso modo, el uso del operador sizeof que nos sirve para obtener el tamaño (en byte) de una enumeración.

8. Glosario

  • Bit a bit
  • Bitwise
  • Desplazamiento bit a la izquierda
  • Desplazamiento bit a la derecha
  • Operador
  • sizeof

9. Literatura & Enlaces

[1]: C# 5.0 in a Nutshell by Joseph Albahari and Ben Albahari. Copyright 2012 Joseph Albahari and Ben Albahari, 978-1-449-32010-2.
[2]: 14.5 Enum values and operations - http://msdn.microsoft.com/en-us/library/aa664601(v=vs.71).aspx
[3]: 7.9.5 Enumeration comparison operators (C#) - http://msdn.microsoft.com/en-us/library/aa664726(v=vs.71).aspx
[4]: Enums in C# - CodeProject - http://www.codeproject.com/Articles/18809/Enums-in-C
[5]: Compiler Error CS0019 - http://msdn.microsoft.com/en-us/library/a63h61ky.aspx
[6]: sizeof (C# Reference) - http://msdn.microsoft.com/en-us/library/eahchzkf.aspx
[7]: Operadores Bitwise (Bit a Bit) en C# | OrtizOL - Experiencias Construcción Software (xCSw) - http://ortizol.blogspot.com/2013/07/operadores-bitwise-bit-bit-en-c.html


J

miércoles, 14 de mayo de 2014

Enumeraciones en C# - Parte 3

Tabla de Contenido

0. Introducción
1. ¿Qué son las Banderas (Flags)?
2. ¿Banderas en Enumeraciones?
2.1 El atributo [Flags]
2.2 Combinación de miembros de una enumeración
2.3 Otras operaciones interesantes
2.4 Notas importantes
3.5 Ejemplos
4. Conclusiones
5. Glosario
5. Literatura & Enlaces

0. Introducción

Esta es la tercera parte acerca de enumeraciones en C#. Vamos a explorar varias de las operaciones a nivel de bits sobre los enums. Aprenderemos que este tipo de operación facilita la combinación de valores de una enumeración como una colección: esto simplifica el número de constantes a declarar. Presentaré hasta 4 ejemplos para ilustrar esta interesante capacidad: días de la semana, los bordes de un cuadrado, ficha de contacto, y los colores de una paleta de colores.



Artículos de la serie:



Parte 1 - Introducción a la enumeraciones en C#

Parte 2 - Operaciones de las enumeraciones
Parte 3 - Valores bandera en las enumeraciones
Parte 4 - Operadores de las enumeraciones
Parte 5 - Casos de seguridad de tipos

1. ¿Qué son las Banderas (Flags)?

Podemos hacer una traducción arbitraria de Flags a español como 'Banderas'. Bueno, en particular en el lenguaje C#, este concepto facilita la conjugación (combinación) de valores predefinidos (las constantes o miembros de la enumeración). Estas combinaciones serán nuevos valores derivados de los originales, es decir, que a partir de una definición simple de constantes podemos obtener nuevas constantes. Esto lo podríamos ejemplificar, de forma natural, con lo que ocurre con los tres colores esenciales: rojo (), verde (), y azul ():

 + =
  = 
  +  =  (Blanco)

Podríamos seguir generando combinaciones según sea necesario.

Otro ejemplo en la asignación de atributos a archivos. Los modos de acceso:
  • Lectura
  • Escritura
  • Ejecución
Este modelo funciona correctamente en los sistemas operativos basados en el kérnel Linux. Para determinar los atributos de un archivo de usuario o de sistema, se combinas estos tres valores (banderas, para el caso que nos corresponde). Así:
  • Lectura [X], Escritura [-], Ejecución [-]
  • Lectura[X], Escritura[X], Ejecución [-]
  • Lectura[-], Escritura[-], Ejecución [X]
Tengamos en cuenta que pudimos generar otras tres combinaciones a partir de las básicas definidas arriba. (Desde luego se podrían generar otras más).

2. Banderas en Enumeraciones

Esta operación de combinación de constantes o miembros de enumeración es posible efectuarla en C#. Sin embargo, hay que tener en cuenta este par de recomendaciones (~reglas) en su definición [1]:
  • Los miembros de la enumeración deben tener un valor asignado.
  • El valor asignado debe ser un número de potencia de dos.
En las siguientes subsecciones veremos la definición, uso, y varios ejemplos.

2.1 El atributo [Flags]

El atributo [Flags] permite especificar que una enumeración va a ser tratada como un cambio en términos de bits. Esta representación es la que permite representar diferentes estados o banderas.

Este atributo se pone por encima de la declaración de la enumeración. De esta manera:

Ejemplo abstracto:

[Flags]
{modificador de acceso} enum {Nombre de la enumeración}
{
// conjunto de miembros
}

Ejemplo particular:

[Flags]
public enum Bordes
{
  Ninguno = 0,
Izquierdo = 1,
Derecho = 2,
Superior = 4,
Inferior = 8
}

Los 5 miembros de la enumeración (i.e., NoneIzquierdoDerechoSuperior, e Inferior) tienen asignados valores explícitos. Estos valores corresponden con potencias de dos: 0, 2^0 = 1, 2^1 = 2, 2^2 = 4, 2^3 = 8, respectivamente.

2.2 Combinación de miembros de una enumeración

Ya hemos dicho que en C# el atributo [Flags] permite asignar de forma implícita un valor binario a las miembros de una enumeración. Ahora, para realizar operaciones de bit-a-bit (bitwise -cfr. Operadores Bitwise (Bit a Bit) en C#-) usamos los operadores:

  • | (OR inclusivo), y
  • & (AND)
Sigamos con el ejemplo de la sección anterior (i.e., enumeración Bordes):

Bordes derechoIzquierdo = Bordes.Derecho | Bordes.Izquierdo;

El valor asignado a la bandera derechoIzquierdo es:

Bordes.Derecho = 2 = 2^1 = 00000010
Bordes.Izquierdo = 1 = 2^0 = 00000001

Aplicamos la operación OR (inclusivo):

00000010 |
00000001
=
00000011

Ahora si queremos saber si una combinación posee un de las definiciones básicas de la enumeración, utilizamos el operador AND:

derechoIzquierdo & Bordes.Derecho

En matemática binaria tenemos:

00000011 &
00000010
=
00000010

Con un instrucción de selección if podemos utilizar un operador de igualdad. De este modo:

if ((derechoIzquierdo & Bordes.Derecho) !=0)
{
Console.WriteLine("Incluye el lado derecho.");
}

Por otro lado, el valor de la variable derechoIzquierdo es igual a:

Console.WriteLine(derechoIzquierdo.ToString()); // Salida: "Derecho, Izquierdo"

2.3 Otras operaciones interesantes

Podemos alternar el valor de una variable tipo enum -Bordes- aplicando uno de los operadores compuestos:

Bordes borde = Bordes.Derecho;
borde |= Bordes.Izquierdo;
Console.WriteLine(borde == (Bordes.Derecho | Bordes.Izquierdo)); // Salida: True

Así mismo:

borde ^= Bordes.Izquierdo;
Console.WriteLine(borde); // Salida: Derecho

Con la penúltima instrucción estamos alternando valores. Con matemática binaria:

00000001 ^
00000011
=
00000010

2.4 Notas importantes

Desde [1] anuncian:
By convention, a combinable enum type is given a plural rather than singular name.
Por otro lado [ídem], en la definición de una enumeración se puede incluir miembros producto de una combinación:

[Flags]
public enum Bordes
{
Ninguno = 0,
Izquierdo = 1,
Derecho = 2,
Superior = 4,
Inferior = 8,
DerechoIzquierdo = Derecho | Izquierdo,
SuperiorInferior = Superior | Inferior,
Todos = DerechoIzquierdo | SuperiorInferior
}

3. Ejemplos

3.1 CRUD

CRUD (Acrónimo de Create, Read, Update, y Delete). Para este conjunto de operaciones vamos a definir una enumeración que definirá las combinaciones de permisos que tiene un usuario sobre una base datos o tabla.

Archivo Crud.cs:



Compilación:


  1. csc /target:exe Crud.cs

> Prueba de ejecución.

Resultado:


Permisos para infzero: Crear, Actualizar

3.2 Días de la semana

Ahora veamos una enumeración con los días de la semana. Esta enumeración nos puede ser de  utilidad para, por ejemplo, un sistema de calendarización que admita la repetición de tareas o eventos programados; o simplemente, la combinaciones estándar: fines de semana, o días laborables, &c.

Archivo DiasSemana.cs:

Compilación:

  1. csc /target:exe SerializacionJson.cs

> Prueba de ejecución.

Resultado:

Resumen del evento:
 Nombre evento: Escribir acerca de enumeraciones en C#.
 Fecha y hora evento: 5/22/2014 1:17:19 PM
 Día(s) evento: Lunes, Miercoles, Viernes

4. Conclusiones

La combinación de miembros de una enumeración nos puede representar un ahorro de tiempo programático en la declaración y uso de este tipo de construcciones en el lenguaje C#. Vimos que es posible trabajar con una representación binaria de los valores asignados a los miembros de una enumeración: bit-a-bit (bitwise).

5. Glosario

  • Binario
  • Bit-a-bit
  • Bitwise
  • Combinación
  • Matemática

6. Literatura & Enlaces

[1]: C# 5.0 in a Nutshell by Joseph Albahari and Ben Albahari. Copyright 2012 Joseph Albahari and Ben Albahari, 978-1-449-32010-2.
[2]: What does the [Flags] Enum Attribute mean in C#? - Stack Overflow - http://stackoverflow.com/questions/8447/what-does-the-flags-enum-attribute-mean-in-c
[3]: C# Enum Flags Attribute - http://www.dotnetperls.com/enum-flags
[4]: banderas en c# | Really Develop - http://josebgd.wordpress.com/tag/banderas-en-c/
[5]: FlagsAttribute Class (System) - http://msdn.microsoft.com/en-us/library/system.flagsattribute(v=vs.110).aspx
[6]: Operadores Bitwise (Bit a Bit) en C# | OrtizOL - Experiencias Construcción Software (xCSw) - http://ortizol.blogspot.com/2013/07/operadores-bitwise-bit-bit-en-c.html


J