2010-02-11 15 views
36

me he preguntado por qué regularidad C# todavía no ha implementado algunas genérico Enum.Parseversión genérica de la Enum.Parse en C#

Digamos que tengo

enum MyEnum 
{ 
    Value1, 
    Value2 
} 

Y a partir de un archivo XML/DB entrada I desea crear un Enum.

MyEnum val = (MyEnum)Enum.Parse(typeof(MyEnum), "value1", true); 

Podría no han puesto en práctica como algo parecido a

MyEnum cal = Enum.Parse<MyEnum>("value1"); 

Esto puede parecer un pequeño problema, pero parece que un alto un.

¿Alguna idea?

Respuesta

30

Ya está implementado en .NET 4;) Eche un vistazo a here.

MyEnum cal; 
if (!Enum.TryParse<MyEnum>("value1", out cal)) 
    throw new Exception("value1 is not valid member of enumeration MyEnum"); 

También la discusión here contiene algunos puntos interesantes.

+6

Ese vínculo es a la no genérico ' Método Enum.Parse'. ¿Quería vincular el nuevo método 'Enum.TryParse '? http://msdn.microsoft.com/en-us/library/system.enum.tryparse%28VS.100%29.aspx –

+3

Es interesante que lo hayan restringido a struct, new() en lugar de agregar una nueva restricción enum al lenguaje. –

+0

Lo siento, ya lo he solucionado, eso es exactamente lo que quise decir;) –

6

Aunque C# no permite la restricción a System.Enum, está permitido en .NET y C# puede utilizar tipos o métodos con tales restricciones. Consulte la biblioteca Unconstrained Melody de Jon Skeet, que incluye un código que hace exactamente lo que usted desea.

+18

Embaucamiento, ni siquiera puedo conectar mi propia biblioteca sin que alguien llegue primero;) –

16

Y en la sintaxis deseada de la pregunta: ¿

MyEnum cal = Toolkit.Parse<MyEnum>("value1"); 

Nota: Desde C# que prohíbe la adición de extensiones estáticas, lo que tiene que albergar la función en otro lugar. yo uso una clase estática Toolkit que contiene todos estos bits útiles:

/// <summary> 
/// Converts the string representation of the name or numeric value of one or 
// more enumerated constants to an equivalent enumerated object. 
/// </summary> 
/// <typeparam name="TEnum">An enumeration type.</typeparam> 
/// <param name="value">A string containing the name or value to convert.</param> 
/// <returns>An object of type TEnum whose value is represented by value</returns> 
/// <exception cref="System.ArgumentNullException">enumType or value is null.</exception> 
/// <exception cref=" System.ArgumentException"> enumType is not an System.Enum. -or- 
/// value is either an empty string or only contains white space.-or- 
/// value is a name, but not one of the named constants defined for the enumeration.</exception> 
/// <exception cref="System.OverflowException">value is outside the range of the underlying type of enumType.</exception> 
public static TEnum Parse<TEnum>(String value) where TEnum : struct 
{ 
    return (TEnum)Enum.Parse(typeof(TEnum), value); 
} 
0

Mientras que pellizcar un poco con algunos métodos, tratando de construir algo similar a la propuesta inicial:

MyEnum cal = Enum.Parse<MyEnum>("value1"); 

me parecía que esta sintaxis no será posible en C#, ya que el tipo Enum se trata como no nulo.

Si llamamos al método "Enum.TryParse" pasando un valor que no corresponde a un elemento de la enumeración, , el valor por defecto de Enum se devolverá en la variable "out". Es por eso que necesitamos para poner a prueba la "Enum.TryParse" número primero, ya que simplemente llamando

MyEnum cal; 
Enum.TryParse<MyEnum>("value1", out cal); 

y la comprobación de valor "CAL" no siempre dará un resultado fiable.

+3

el 'Parse' genérico podría ser simplemente un envoltorio alrededor de' TryParse' y arrojar 'ArgumentException' si' TryParse' devuelve 'false'. –

+0

Puede simplemente aumentar la excepción en lugar del valor predeterminado. Lo mismo que la versión no genérica de Parse. – Maxim

+0

La idea es evitar (cuando sea posible) el manejo de excepciones, que se considera un antipatrón para el control de flujo (ref. Https://web.archive.org/web/20140430044213/http://c2.com/cgi- bin/wiki? DontUseExceptionsForFlowControl). De acuerdo con su especificación API, el método Enum.TryParse "elimina la necesidad del manejo de excepciones al analizar la representación de cadena de un valor de enumeración". (ref. https://msdn.microsoft.com/en-us//library/dd991317(v=vs.110).aspx) –

2
public class EnumHelper 
{ 
    public static T? TryParse<T>(string text) 
     where T: struct 
    { 
     if (string.IsNullOrEmpty(text)) 
     { 
      return null; 
     } 

     T r; 

     if (Enum.TryParse<T>(text, out r)) 
     { 
      return r; 
     } 

     return null; 
    } 
} 
1

ligeramente modificada versión de @ respuesta de Ian-Boyd, utilizando un método de extensión para evitar la necesidad de especificar un nombre de clase estática en la llamada:

MyEnum cal = "value1".Parse<MyEnum>(); 

/// <summary> 
/// Converts the string representation of the name or numeric value of one or 
// more enumerated constants to an equivalent enumerated object. 
/// </summary> 
/// <typeparam name="TEnum">An enumeration type.</typeparam> 
/// <returns>An object of type TEnum whose value is represented by value</returns> 
/// <exception cref="System.ArgumentNullException">enumType or value is null.</exception> 
/// <exception cref=" System.ArgumentException"> enumType is not an System.Enum. -or- 
/// value is either an empty string or only contains white space.-or- 
/// value is a name, but not one of the named constants defined for the enumeration.</exception> 
/// <exception cref="System.OverflowException">value is outside the range of the underlying type of enumType.</exception> 
public static TEnum Parse<TEnum>(this String value) where TEnum : struct 
{ 
    return (TEnum)Enum.Parse(typeof(TEnum), value); 
}