Quiero escribir una función que pueda validar un valor dado (pasado como una cadena) contra posibles valores de un enum
. En el caso de una coincidencia, debería devolver la instancia enum; de lo contrario, debería devolver un valor predeterminado.
La función no puede usar internamente try
/ catch
, lo que excluye el uso Enum.Parse
, lo que genera una excepción cuando se le da un argumento no válido.
Me gustaría usar algo parecido a una TryParse
función para implementar esto:
public static TEnum ToEnum<TEnum>(this string strEnumValue, TEnum defaultValue)
{
object enumValue;
if (!TryParse (typeof (TEnum), strEnumValue, out enumValue))
{
return defaultValue;
}
return (TEnum) enumValue;
}
Respuestas:
Como han dicho otros, tienes que implementar el tuyo propio
TryParse
. Simon Mourier está proporcionando una implementación completa que se encarga de todo.Si está utilizando enumeraciones de campo de bits (es decir, banderas), también debe manejar una cadena como la
"MyEnum.Val1|MyEnum.Val2"
que es una combinación de dos valores de enumeración. Si solo llamaEnum.IsDefined
con esta cadena, devolverá falso, aunque loEnum.Parse
maneje correctamente.Actualizar
Como lo mencionaron Lisa y Christian en los comentarios,
Enum.TryParse
ahora está disponible para C # en .NET4 y versiones posteriores.Documentos de MSDN
fuente
Enum.IsDefined hará las cosas. Puede que no sea tan eficiente como probablemente sería TryParse, pero funcionará sin manejo de excepciones.
Cabe destacar: un
TryParse
método se añadió en .NET 4.0.fuente
GetNames
. Internamente, todos estos métodos (incluidosParse
) utilizanGetHashEntry
, que hace la reflexión real, una vez. En el lado positivo, .NET 4.0 tiene un TryParse, y también es genérico :)Aquí hay una implementación personalizada de
EnumTryParse
. A diferencia de otras implementaciones comunes, también admite la enumeración marcada con elFlags
atributo.fuente
Activator.CreateInstance(type)
para crear el valor de enumeración predeterminado y noEnum.ToObject(type, 0)
. ¿Solo es cuestión de gustos?Al final, debes implementar esto en torno a
Enum.GetNames
:Notas adicionales:
Enum.TryParse
está incluido en .NET 4. Consulte aquí http://msdn.microsoft.com/library/dd991876(VS.100).aspxEnum.Parse
captura de la excepción lanzada cuando falla. Esto podría ser más rápido cuando se encuentra una coincidencia, pero es probable que sea más lento si no. Dependiendo de los datos que esté procesando, esto puede ser o no una mejora neta.EDITAR: Acabo de ver una mejor implementación en esto, que almacena en caché la información necesaria: http://damieng.com/blog/2010/10/17/enums-better-syntax-improved-performance-and-tryparse-in-net- 3-5
fuente
Flags
atributo.Basado en .NET 4.5
Código de muestra a continuación
Referencia: http://www.dotnetperls.com/enum-parse
fuente
Tengo una implementación optimizada que podría usar en UnconstrainedMelody . Efectivamente, solo está almacenando en caché la lista de nombres, pero lo está haciendo de una manera agradable, fuertemente tipada y genéricamente restringida :)
fuente
...
fuente
Actualmente no hay Enum.TryParse. Esto se solicitó en Connect ( todavía no hay Enum.TryParse ) y obtuvo una respuesta que indica una posible inclusión en el siguiente marco después de .NET 3.5. Tendrá que implementar las soluciones sugeridas por ahora.
fuente
La única forma de evitar el manejo de excepciones es usar el método GetNames (), y todos sabemos que no se debe abusar de las excepciones para la lógica de aplicación común :)
fuente
¿Se permite el almacenamiento en caché de una función / diccionario generado dinámicamente?
Debido a que no (parece) conocer el tipo de enumeración de antemano, la primera ejecución podría generar algo que las ejecuciones posteriores podrían aprovechar.
Incluso podría almacenar en caché el resultado de Enum.GetNames ()
¿Estás intentando optimizar para CPU o memoria? ¿De verdad lo necesitas?
fuente
Como ya han dicho otros, si no usa Try & Catch, necesita usar IsDefined o GetNames ... Aquí hay algunos ejemplos ... básicamente son todos iguales, el primero que maneja enumeraciones que aceptan valores NULL. Prefiero el segundo ya que es una extensión de cadenas, no enumeraciones ... ¡pero puedes mezclarlas como quieras!
fuente
No hay un TryParse porque el tipo de Enum no se conoce hasta el tiempo de ejecución. Un TryParse que sigue la misma metodología que, por ejemplo, el método Date. TryParse arrojaría un error de conversión implícito en el parámetro ByRef.
Sugiero hacer algo como esto:
fuente
Try
métodos cuyos resultados pueden ser tipos de valor, o dondenull
puede ser un resultado legítimo (por ejemplo, elDictionary.TryGetValue, which has both such traits), the normal pattern is for a
método Try` para devolverbool
y pasar el resultado como unout
parámetro. Para aquellos que devuelven tipos de clase dondenull
no es un resultado válido, no hay dificultad en usar unnull
retorno para indicar falla.Eche un vistazo a la clase Enum (¿estructura?). Hay un método Parse sobre eso, pero no estoy seguro de un tryparse.
fuente
Este método convertirá un tipo de enumeración:
Comprueba el tipo subyacente y obtiene el nombre para analizarlo. Si todo falla, devolverá el valor predeterminado.
fuente