2010-07-28 18 views
5

Estoy tratando de devolver un valor de Enumeración fuertemente tipado de una cadena. Estoy seguro de que hay una mejor manera de hacer esto. Esto simplemente parece demasiado código para algo tan simple como esto:Cómo devolver un valor Enum a partir de una cadena?

public static DeviceType DefaultDeviceType 
    { 
     get 
     { 
      var deviceTypeString = GetSetting("DefaultDeviceType"); 
      if (deviceTypeString.Equals(DeviceType.IPhone.ToString())) 
       return DeviceType.IPhone; 
      if (deviceTypeString.Equals(DeviceType.Android.ToString())) 
       return DeviceType.Android; 
      if (deviceTypeString.Equals(DeviceType.BlackBerry.ToString())) 
       return DeviceType.BlackBerry; 
      if (deviceTypeString.Equals(DeviceType.Other.ToString())) 
       return DeviceType.Other; 
      return DeviceType.IPhone; // If no default is provided, use this default. 
     } 
    } 

Ideas?

Basado en los comentarios que recibí de la comunidad, he decidido utilizar una extensión de método que convierta una cadena en una enumeración. Toma un parámetro (el valor de enumeración predeterminado). Ese valor predeterminado también proporciona el tipo, por lo que se puede inferir el genérico y no es necesario especificarlo explícitamente usando <>. El método ahora se abrevia a esto:

public static DeviceType DefaultDeviceType 
    { 
     get 
     { 
      return GetSetting("DefaultDeviceType").ToEnum(DeviceType.IPhone); 
     } 
    } 

Solución muy buena que puede reutilizarse en el futuro.

Respuesta

13

Si se trata de una entrada de usuario (no confiable), me gusta usar un método de extensión que permita un valor predeterminado. Pruébalo.

public static TResult ParseEnum<TResult>(this string value, TResult defaultValue) 
    { 
     try 
     { 
      return (TResult)Enum.Parse(typeof(TResult), value, true); 
     } 
     catch (ArgumentException) 
     { 
      return defaultValue; 
     } 
    } 
+0

Muy bueno, me gusta la capacidad de proporcionar un valor predeterminado: probablemente termine usando esto. Gracias. –

+3

Este es un buen enfoque. Dependiendo de su versión de .NET, el nuevo Enum.TryParse le permite mantener este mismo método mientras se deshace del bloque try. – TechNeilogy

+0

@TechNeilogy Estoy usando .net 3.5, no vi el método TryParse, ¿debe ser nuevo con 4.0? –

15

Uso Enum.Parse():

var deviceTypeString = GetSetting("DefaultDeviceType"); 
return (DeviceType)Enum.Parse(typeof(DeviceType), deviceTypeString); 

Si la entrada no es fiable, se debe tener cuidado, porque obtendrá un ArgumentException si el valor no puede ser interpretado como uno de los valores de la enumeración.

También hay una sobrecarga de Parse() que le permite ignorar el caso al hacer esta conversión, si es necesario.

+0

Niza, que es mucho mejor. ¡Gracias! –

1

he escrito este método de extensión una vez para convertir a cualquier cualquier tipo de enumeración de cuerda, de esta manera usted no tiene que escribir el código de conversión una y otra vez:

public static class StringExtensions 
    { 

    public static T ConvertToEnum<T>(this string value) 
    { 
     //Guard condition to not allow this to be used with any other type than an Enum 
     if (typeof(T).BaseType != typeof(Enum)) 
     { 
      throw new InvalidCastException(string.Format("ConvertToEnum does not support converting to type of [{0}]", typeof(T))); 
     } 


     if (Enum.IsDefined(typeof(T), value) == false) 
     { 
      //you can throw an exception if the string does not exist in the enum 
      throw new InvalidCastException(); 

      //If you prefer to return the first available enum as the default value then do this 
      Enum.GetNames(typeof (T))[0].ConvertToEnum<T>(); //Note: I haven't tested this 
     } 
     return (T)Enum.Parse(typeof(T), value); 
    } 
} 

utilizar realmente se le puede hacer esto:

//This is a enumeration for testing 
enum MyEnumType 
{ 
    ENUM1, 
    ENUM2 
} 

//How to cast 
var myEnum = "ENUM2".ConvertToEnum<MyEnumType>(); 

MyEnum en este punto debe ser igual ENUM2

+0

¡Eso es resbaladizo! Lo único que no vi es cómo manejar el caso cuando falla un análisis sintáctico, ¿qué predeterminado debe usarse? Tal vez pueda agregar una sobrecarga para pasar el valor predeterminado al método de extensión. –

+0

Estoy pensando que si expongo un método que no toma un valor predeterminado, entonces puedo usar el primer valor de enumeración (por defecto). ¿Sabes cómo obtener el primer valor de enumeración, mientras usas un genérico como en el código anterior? –

+0

@Paul gracias, bueno, si el análisis falla, personalmente me gustaría saberlo y lanzo una excepción. No me gustaría devolver un valor predeterminado porque posiblemente podría causar algunos errores lógicos, cuando asumo que el análisis funciona, pero en realidad está fallando y realmente solo devuelve un valor predeterminado. – 7wp

Cuestiones relacionadas