2012-07-31 16 views
8

¿Alguien tiene una solución más elegante para analizar enumeraciones? Lo siguiente me parece un desastre.Analizando con elegancia C# Enums

UserType userType = (UserType)Enum.Parse(typeof(UserType), iUserType.ToString()); 

Respuesta

13

a menudo hacerle una ayuda genérica para ello:

public static T ParseEnum<T>(string value) where T:struct 
{ 
    return (T)Enum.Parse(typeof(T), value); 
} 

Usted puede combinar eso con Jon Skeet'sUnstrained Melody (o cualquier otro procesador de post IL) para obtener una restricción de tipo adecuado en una enumeración, pero eso es opcional.

A continuación, puede utilizar de esta manera:

var enumValue = ParseEnum<UserType>(iUserType.ToString()); 

El .NET Framework 4.0 también viene con Enum.TryParse que también ofrece una sintaxis similar, y ofrece una manera de manejar si falla el análisis. Por ejemplo:

UserType userType; 
if (Enum.TryParse<UserType>(iUserType.ToString(), out userType)) 
{ 
    //Yay! Parse succeeded. The userType variable has the value. 
} 
else 
{ 
    //Oh noes! The parse failed! 
} 
+0

Me estoy dando cuenta de que para el Enum.TryParse(), el análisis nunca falla, aunque lo quiero para los valores que no están dentro de la enumeración. Mi ejemplo está en: https://pastebin.com/fZfT69Lk – Colin

+0

@Colin - interesante. Esto se debe a que un valor entero siempre es convertible a una enumeración, por ejemplo, '(TestEnum) 4737373' funciona y se compila también. Si desea hacer cumplir que su valor es un valor con nombre, puede usar GetNames para asegurarse de que esté allí. – vcsjones

3

Se puede crear un método extesion como esto

public static class EnumExtensions 
{ 
    public static T ToEnum<T>(this string s) 
    { 
     return (T)Enum.Parse(typeof(T), s); 
    } 
} 

luego en código que puede utilizar de esta manera (MyEnum contiene los valores A y B):

string s = "B"; 
MyEnum e = s.ToEnum<MyEnum>(); 
1

Aquí hay un método de extensión basado en la versión y comentarios de @vcsjones, y en el ejemplo de @Mones:

public enum TestEnum 
{ 
    None, 
    A, 
    B, 
}; 

void Main() 
{ 
    var testValues = new List<object>(); 
    testValues.AddRange(Enumerable.Range(-2, 6).Select(i => (object)i)); 
    testValues.AddRange(new List<string>() { String.Empty, "A", "B", "C", null }); 

    foreach (var testValue in testValues) 
    { 
     Console.WriteLine($"Testing value {testValue ?? String.Empty}:"); 
     TestEnum output; 
     var enumValues = Enum.GetNames(typeof(TestEnum)).ToList(); 
     try 
     { 
      if (TestEnum.TryParse(testValue.ToString(), out output)) 
      { 
       Console.WriteLine($"Succeeded with TryParse on {testValue} to {output}"); 
      } 
      else 
      { 
       Console.WriteLine($"Failed to TryParse on {testValue}"); 
      } 
     } 
     catch (Exception ex) 
     { 
      Console.WriteLine($"Test harness caught an exception: {ex.ToString()}"); 
     } 

     var toEnumOutput = (testValue ?? String.Empty).ToString().Parse<TestEnum>(); 
     Console.WriteLine($"Parse<TEnum> returned {toEnumOutput}"); 

     Console.WriteLine(); 
     Console.WriteLine(); 
    } 

} 


public static class EnumExtensions 
{ 
    public static TEnum Parse<TEnum>(this string value) where TEnum : struct 
    { 
     TEnum output = default(TEnum); 
     var enumValues = Enum.GetNames(typeof(TEnum)).ToList(); 

     if (Enum.TryParse<TEnum>(value, true, out output)) 
      if (Enum.IsDefined(typeof(TEnum), value) || value.ToString().Contains(",") || enumValues.Contains(output.ToString())) 
      { 
       Console.WriteLine($"Converted '{value}' to {output}."); 
       return output; 
      } 
      else 
      { 
       Console.WriteLine($"{value} is not an underlying value of the enumeration."); 
      } 
     else 
     { 
      Console.WriteLine($"{value} is not a member of the enumeration."); 
     } 
     return default(TEnum); 
    } 
} 

El instrumento de prueba da este resultado:

Testing value -2: 
Succeeded with TryParse on -2 to -2 
-2 is not an underlying value of the enumeration. 
Parse<TEnum> returned None 


Testing value -1: 
Succeeded with TryParse on -1 to -1 
-1 is not an underlying value of the enumeration. 
Parse<TEnum> returned None 


Testing value 0: 
Succeeded with TryParse on 0 to None 
Converted '0' to None. 
Parse<TEnum> returned None 


Testing value 1: 
Succeeded with TryParse on 1 to A 
Converted '1' to A. 
Parse<TEnum> returned A 


Testing value 2: 
Succeeded with TryParse on 2 to B 
Converted '2' to B. 
Parse<TEnum> returned B 


Testing value 3: 
Succeeded with TryParse on 3 to 3 
3 is not an underlying value of the enumeration. 
Parse<TEnum> returned None 


Testing value : 
Failed to TryParse on 
is not a member of the enumeration. 
Parse<TEnum> returned None 


Testing value A: 
Succeeded with TryParse on A to A 
Converted 'A' to A. 
Parse<TEnum> returned A 


Testing value B: 
Succeeded with TryParse on B to B 
Converted 'B' to B. 
Parse<TEnum> returned B 


Testing value C: 
Failed to TryParse on C 
C is not a member of the enumeration. 
Parse<TEnum> returned None 


Testing value : 
Test harness caught an exception: System.NullReferenceException: Object reference not set to an instance of an object. 
    at UserQuery.Main() in C:\Users\Colin\AppData\Local\Temp\3\LINQPad5\_zhvrhwll\query_ludjga.cs:line 49 
is not a member of the enumeration. 
Parse<TEnum> returned None 

Referencias:

+1

Veo que trabajó duro para crear una respuesta bien documentada con un buen conjunto de pruebas. Eso es realmente genial, pero permítame alentarlo a que intente utilizar algún marco de prueba de unidad. Cualquiera, son realmente similares estos años. Estoy tentado de reescribir tus pruebas con ** xUnit ** (realmente me gusta eso, solo enlazo un nuget y listo) para mostrarte lo genial/legible que puede ser, pero ... probablemente te beneficiarías más Hágalo usted mismo. Envíame un mensaje si quieres probar y quedarte atrapado en algo. – quetzalcoatl

+0

Hola @quetzalcoatl - aprecia los comentarios.Agrego pruebas nUnit y luego publico un enlace a mi clase de prueba. – Colin