Wpf – Enumeraciones con opciones múltiples

Descripción general:

Estudio de como usar una funcion que trabaje y use una enumeracion multiple, marcada con el atributo [FlagsAttribute]

Wpf – Enumeraciones con opciones múltiples

Las enumeraciones con opciones múltiples son aquellas que están marcadas con el atributo [ FlagsAttribute() ] y que permiten elegir varias opciones a la vez, en lugar de una sola, por ejemplo, podemos elegir en una supuesta enumeración el grabar un texto en disco, y ademas, en un archivo

Un poco de código (mío) a modo de ejemplo:

Este código esta copiado de una clase que cambia los caracteres por sus entidades, Ejemplo; Reemplazar [á], por [á] para XML o bien por [á] para HTML. Es decir, solo muestra la idea de como se hace, pero no es un código funcional.

Consta de la enumeración que esta marcada con el atributo [ FlagsAttribute ], y una función que muestra como se usa esa enumeración para ejecutar varios procesos

Previamente, en el código elijo el tipo de carácter a convertir, por ejemplo


Dim tipoDeConversion As EConvertir = EConvertir.SoloVocalesAcentuadas Or EConvertir.SoloAngulitos

Esta es la enumeración que utilizo


    <FlagsAttribute()>
    Public Enum EConvertir
        None = 0
        SoloAmpersand = 1
        SoloAngulitos = 2
        SoloComilasDobles = 4
        SoloComilasSencillas = 8
        SoloCaracteres = 16
        SoloVocalesAcentuadas = 32
        ''' <summary>
        '''     Convierte todos los caracteres (todo lo anterior junto)
        ''' </summary>
        Todo = 64
    End Enum

El código (Vb) que usa esta enumeración


     ''' -------------------------------------------------
        ''' <summary>
        '''   Cambia los caracteres especiales por su entidad equivalente,
        '''   por ejemplo las vocales acentuadas por su entidad
        ''' </summary>
        ''' <param name = "paramUnaCadena">
        ''' La cadena que se va a explorar y en la que se van a convertir los caracteres especiales</param>
        ''' <param name = "paramTipoConversionE">
        '''    Que caracteres se convierte, las vocales, los angulitos, etc</param>
        ''' <param name = "paramTipoEntidadE">que entidad quiero obtener, para HTML o para XML</param>
        ''' <returns>La cadena con los caracteres especiales convertidos en entidades</returns>
        ''' -------------------------------------------------
        Public Shared Function CaracterToEntidad(
                            ByVal paramUnaCadena As String,
                            ByVal paramTipoConversionE As EConvertir,
                            ByVal paramTipoEntidadE As EEntidades) As String
            '------------------------------------------
            ' Control del parámetro
            '------------------------------------------
            ' no se permiten valore nothing, ni empty, ni WhiteSpace en la cadena de entrada
            ' no se permiten valores NONE en las enumeraciones
                  '------------------------------------------
            ' la cadena de salida inicial
            Dim cadenaSalida As String = paramUnaCadena
            Dim controlParanoico As Boolean
            Try
                controlParanoico = False
                If paramTipoConversionE = EConvertir.None Then
                      ' No acepto este valor
                    Call DispararErrorEnumeracionNoPuedeTomarEseValor(Etc, etc)
                End If
                'None = 0
                'SoloAmpersand = 1
                'SoloAngulitos = 2
                'SoloComilasDobles = 4
                'SoloComilasSencillas = 8
                'SoloCaracteres = 16
                'SoloVocalesAcentuadas = 32
                'Todo = 64
                '------------------------------------
                ' opciones multiples
                If (paramTipoConversionE And EConvertir.SoloAmpersand) = EConvertir.SoloAmpersand Then
                    ' código correspondiente a esta opcion de la enumeracion. Por ejemplo
                    cadenaSalida = AmpersandToEntidad(cadenaSalida, paramTipoEntidadE)
                    controlParanoico = True
                End If
                If (paramTipoConversionE And EConvertir.SoloAngulitos) = EConvertir.SoloAngulitos Then
                    ' código correspondiente a esta opcion de la enumeracion. Por ejemplo
                    cadenaSalida = AngulitosToEntidad(paramUnaCadena, paramTipoEntidadE)
                    controlParanoico = True
                End If
                If (paramTipoConversionE And EConvertir.SoloComilasDobles) = EConvertir.SoloComilasDobles Then
                    ' código correspondiente a esta opcion de la enumeracion. Por ejemplo
                    cadenaSalida = ComillasDoblesToEntidad(paramUnaCadena, paramTipoEntidadE)
                    controlParanoico = True
                End If
                If (paramTipoConversionE And EConvertir.SoloComilasSencillas) = EConvertir.SoloComilasSencillas Then
                    ' código correspondiente a esta opcion de la enumeracion. Por ejemplo
                    cadenaSalida = ComillasSencillasToEntidad(paramUnaCadena, paramTipoEntidadE)
                    controlParanoico = True
                End If
                If (paramTipoConversionE And EConvertir.SoloCaracteres) = EConvertir.SoloCaracteres Then
                    ' código correspondiente a esta opcion de la enumeracion. Por ejemplo
                    cadenaSalida = CaracteresToEntidad(paramUnaCadena, paramTipoEntidadE)
                    controlParanoico = True
                End If
                If (paramTipoConversionE And EConvertir.SoloVocalesAcentuadas) = EConvertir.SoloVocalesAcentuadas Then
                    ' código correspondiente a esta opcion de la enumeracion. Por ejemplo
                    cadenaSalida = VocalesAcentuadasToEntidad(paramUnaCadena, paramTipoEntidadE)
                    controlParanoico = True
                End If
                If (paramTipoConversionE And EConvertir.Todo) = EConvertir.Todo Then
                    ' código correspondiente a esta opcion de la enumeracion. Por ejemplo
                    cadenaSalida = AmpersandToEntidad(paramUnaCadena, paramTipoEntidadE)
                    cadenaSalida = AngulitosToEntidad(cadenaSalida, paramTipoEntidadE)
                    cadenaSalida = ComillasDoblesToEntidad(cadenaSalida, paramTipoEntidadE)
                    cadenaSalida = ComillasSencillasToEntidad(paramUnaCadena, paramTipoEntidadE)
                    cadenaSalida = VocalesAcentuadasToEntidad(paramUnaCadena, paramTipoEntidadE)
                    cadenaSalida = CaracteresToEntidad(cadenaSalida, paramTipoEntidadE)
                    controlParanoico = True
                End If
                If controlParanoico = False Then
                    ' Quiere decir que algo no ha funcionado
                     Throw New ArgumentException(etc,etc)
               End If
            Catch ex As System.Exception
                Throw
            End Try
            '-------------------------------------------
            Return cadenaSalida
        End Function

La documentación MSDN indica lo siguiente para este tipo de enumeraciones:

Comentarios

Los campos de bits se utilizan normalmente para las listas de elementos que se pueden producir en combinación, mientras que las constantes de enumeración se suelen usar para listas de elementos mutuamente excluyentes. Por lo tanto, los campos de bits están diseñados para combinarse con una operación OR bit a bit para generar valores sin nombre, mientras que las constantes enumeradas no lo son. Los lenguajes varían en el uso de campos de bits en comparación con las constantes de enumeración.

Directrices para FlagsAttribute y Enum

  • Utilice el atributo personalizado  FlagsAttribute para una enumeración sólo si se va a realizar una operación bitwise (AND, OR, EXCLUSIVE OR) en un valor numérico.
  • Defina constantes de enumeración en potencias de dos, es decir, 1, 2, 4, 8, etc. Esto significa que los indicadores individuales de las constantes de enumeración combinadas no se superponen.
  • Considere la posibilidad de crear una constante enumerada para las combinaciones de indicadores de uso común. Por ejemplo, si tiene una enumeración utilizada para operaciones de E / S de archivo que contiene las constantes enumeradas Read = 1 y Write = 2, considere la posibilidad de crear la constante enumerada ReadWrite = Read OR Write, que combina los indicadores de lectura y escritura. Además, la operación OR bit a bit utilizada para combinar los indicadores podría considerarse un concepto avanzado en algunas circunstancias que no debería ser necesario para tareas simples.
  • Tenga cuidado si define un número negativo como una constante enumerada de indicador porque muchas posiciones de indicador pueden establecerse en 1, lo que podría confundir el código y fomentar errores de codificación.
  • Una forma conveniente de probar si un indicador se establece en un valor numérico es realizar una operación AND bitwise entre el valor numérico y la constante enumerada de indicador, que establece todos los bits del valor numérico en cero que no corresponden al indicador, luego probar si el resultado de esa operación es igual a la constante enumerada de indicador.
  • Utilíce NONE como nombre de la constante enumerada de indicadores cuyo valor es cero. No se puede utilizar la constante enumerada NONE en una operación AND bitwise para probar un indicador porque el resultado siempre es cero. Sin embargo, puede realizar una comparación lógica, no bitwise, entre el valor numérico NONE y la constante enumerada para determinar si se establecen bits en el valor numérico.
  • Si crea una enumeración de valores en lugar de una enumeración de indicadores, vale la pena crear una constante enumerada NONE . La razón es que, de forma predeterminada, la memoria utilizada para la enumeración se inicializa a cero por Common Language Runtime. En consecuencia, si no define una constante cuyo valor es cero, la enumeración contendrá un valor ilegal cuando se cree.
  • Si hay un caso predeterminado obvio que la aplicación necesita representar, considere la posibilidad de usar una constante enumerada cuyo valor sea cero para representar el valor predeterminado. Si no hay ningún caso predeterminado, considere la posibilidad de usar una constante enumerada cuyo valor sea cero, es decir, el caso que no está representado por ninguna de las otras constantes enumeradas.
  • No defina un valor de enumeración únicamente para reflejar el estado de la enumeración en sí. Por ejemplo, no defina una constante enumerada que simplemente marque el final de la enumeración. Si necesita determinar el último valor de la enumeración, compruebe ese valor explícitamente. Además, puede realizar una comprobación de rango para la primera y la última constante enumerada si todos los valores dentro del rango son válidos.
  • No especifique constantes enumeradas que estén reservadas para su uso futuro.
  • Cuando defina un método o propiedad que tome una constante enumerada como valor, considere la posibilidad de validar el valor. La razón es que puede convertir un valor numérico al tipo de enumeración incluso si ese valor numérico no está definido en la enumeración.