sábado, 23 de agosto de 2014

Enum


Cuando en un código se comparan cadenas, siempre me pregunto porque no usaron enum o constantes.Tal vez no venga mal hacer un recordatorio de que es un enum.
La primera cosa que hay que saber es que son enteros, representa un valor numérico. (MSDN)


Como Char
Esto tal vez para alguno sea un problema, porque lo que queríamos era tener un char. La cantidad de veces que en la base de datos tenemos un char que significa algo.

Ejemplo:
Son valores, numéricos así que siempre puedes transformarlo a su valor ASCII
Public Enum Respuestas
    undefine = AscW(" ")
    SI = AscW("S")
    NO = AscW("N")
End Enum

Dim omiRespuesta As Respuestas = [Enum].Parse(GetType(Respuestas), "SI")
Console.WriteLine("MiRespuesta  {0:D},  como texto {0}", omiRespuesta)
omiRespuesta = [Enum].Parse(GetType(Respuestas), AscW("S"))
Console.WriteLine("MiRespuesta  {0:D}, como texto {0}", omiRespuesta)
Salida
MiRespuesta 83, como texto SI
MiRespuesta 83, como texto SI


Por supuesto que soluciones hay varias.. pero esta es la que me parece más elegante.

Usarlos como un conjunto de marcas
Hay que considerar que los valores deben ser potencias de 2 (MSDN)

Ejemplo:
<FlagsAttribute()> _
Public Enum DiasSemana
    undefine = 1 << 0
    Lunes = 1 << 1
    Martes = 1 << 2
    Miercoles = 1 << 3
    Jueves = 1 << 4
    Viernes = 1 << 5
    Sabado = 1 << 6
    Domingo = 1 << 7
    DiasLaborables = Lunes Or Martes Or Miercoles Or Jueves Or Viernes
    FinDeSemana = Sabado Or Domingo
End Enum
Dim aux As DiasSemana = DiasSemana.Lunes
       
Dim cad As String = String.Join(",",[Enum].GetValues(GetType(DiasSemana)).Cast(Of DiasSemana).ToList().FindAll(Function(x) DiasSemana.FinDeSemana.HasFlag(x) AndAlso x <> DiasSemana.FinDeSemana))
Console.WriteLine("El fin de semana son los: " & cad)
Console.WriteLine(" ------ ")
If DiasSemana.DiasLaborables.HasFlag(aux) Then
                Console.WriteLine(" el {0} es {1}. Num {0:d} - {1:d} ", aux, DiasSemana.DiasLaborables)
Else
                Console.WriteLine("el {0} no es {1}. Num {0:d} - {1:d}", aux, DiasSemana.DiasLaborables)
End If
Console.WriteLine("  ------ ")
Console.WriteLine("el {0}  or   {1}  :  {2}. {0:d} or  {1:d} :{2:d}", aux, DiasSemana.DiasLaborables, aux Or DiasSemana.DiasLaborables)
Console.WriteLine("el {0} xor   {1}  :  {2}. {0:d} Xor {1:d} :{2:d}", aux, DiasSemana.DiasLaborables, aux Xor DiasSemana.DiasLaborables)
Console.WriteLine("el {0} and   {1}  :  {2}. {0:d} and {1:d} :{2:d}", aux, DiasSemana.DiasLaborables, aux And DiasSemana.DiasLaborables)
Console.WriteLine("  ------ ")
If aux.HasFlag(DiasSemana.DiasLaborables) Then
       Console.WriteLine("el {0} es {1}. Num {0:d} - {1:d} ", aux, DiasSemana.DiasLaborables)
Else
       Console.WriteLine("el {0} no es {1}. Num {0:d} - {1:d}", aux, DiasSemana.DiasLaborables)
End If         

Salida
El fin de semana son los: Sabado,Domingo
------
el Lunes es DiasLaborables. Num 2 - 62
------
el Lunes or DiasLaborables : DiasLaborables. 2 or 62 :62
el Lunes xor DiasLaborables : Martes, Miercoles, Jueves, Viernes. 2 Xor 62 :60
el Lunes and DiasLaborables : Lunes. 2 and 62 :2
------
el Lunes no es DiasLaborables. Num 2 - 62

Hay que tener algunas consideraciones con esto. Normalmente usamos los enum de manera exclusiva. Si por ejemplo estamos en un select case como este:
Dim dias As DiasSemana = DiasSemana.Lunes Or DiasSemana.Martes
Select Case dias
Case DiasSemana.Lunes
Console.WriteLine("  Lunes ")
Case DiasSemana.Martes
Console.WriteLine("  Martes ")
Case DiasSemana.DiasLaborables
Console.WriteLine("  laborable ")
Case Else
Console.WriteLine("  otro ")
End Select
La salida será otro ¡!!

Una opción es crear un diccionario  con lo que queremos hacer cada día de la semana y obtener todas la acciones que cumplen con nuestra condición.  
Dim lstQueHacer As Dictionary(Of DiasSemana, Action) = New Dictionary(Of DiasSemana, Action)
lstQueHacer.Add(DiasSemana.Lunes, Sub() Console.WriteLine("hacer los lunes.."))
lstQueHacer.Add(DiasSemana.Martes, Sub() Console.WriteLine("hacer los  martes.."))
lstQueHacer.Add(DiasSemana.Miercoles, Sub() Console.WriteLine("hacer los  miercoles.."))
lstQueHacer.Add(DiasSemana.DiasLaborables, Sub() Console.WriteLine("hacer todos los dias laborables.."))

Dim flags As List(Of DiasSemana) = [Enum].GetValues(GetType(DiasSemana)).Cast(Of DiasSemana).ToList().FindAll(Function(x) dias.HasFlag(x) Or x.HasFlag(dias))
For Each oDia As DiasSemana In flags
                lstQueHacer(oDia)()
Next
Salida
hacer los lunes..
hacer los martes..
hacer todos los dias laborables..

Como verás he hecho dias.HasFlag(x) Or x.HasFlag(dias)) esto es asi porque yo quería que me dijera que hacer los lunes, los martes y las cosas comunes para los días laborables.

Dejo este enlace por si alguno tiene otras dudas


No hay comentarios:

Publicar un comentario