2010-10-06 16 views
10

enumeración Supongamos:cadena genérico para ENUM conversión

public enum SysLogsAppTypes { None, MonitorService, MonitorTool }; 

y aquí hay una función para convertir de la representación ToString() de nuevo a enum:

private SysLogsAppTypes Str2SysLogsAppTypes(string str) 
{ 
    try 
    { 
     SysLogsAppTypes res = (SysLogsAppTypes)Enum 
             .Parse(typeof(SysLogsAppTypes), str); 
     if (!Enum.IsDefined(typeof(SysLogsAppTypes), res)) 
      return SysLogsAppTypes.None; 
     return res; 
    } 
    catch 
    { 
    return SysLogsAppTypes.None; 
    } 
} 

¿Hay una manera de hacer esto Genérico ??

me trataron:

private T Str2enum<T>(string str) 
{ 
    try 
    { 
     T res = (T)Enum.Parse(typeof(T), str); 
     if (!Enum.IsDefined(typeof(T), res)) return T.None; 
     return res; 
    } 
    catch 
    { 
     return T.None; 
    } 
} 

pero me sale: 'T' es un 'parámetro de tipo', que no es válida en el contexto dado
donde hay T.None

Cualquier ayuda ? Gracias

+2

Sólo sustituir 'predeterminado (T)' para 'T.None' y estás listo para irte. – thecoop

Respuesta

10

creo que la palabra clave default es lo que necesita:

private T Str2enum<T>(string str) where T : struct 
{ 
    try 
    { 
     T res = (T)Enum.Parse(typeof(T), str); 
     if (!Enum.IsDefined(typeof(T), res)) return default(T); 
     return res; 
    } 
    catch 
    { 
     return default(T); 
    } 
} 
+5

Esta es la respuesta correcta, pero es importante tener en cuenta que la enumeración "predeterminada" es cualquier valor representado por 0. Este suele ser el primer valor. Sin embargo, si su enumeración comienza en 1, devolverá '0' en lugar de cualquier valor legal en la enumeración. Usar este método requeriría una advertencia para este comportamiento o algún estándar de codificación. Por ejemplo, he visto algunas enumeraciones donde un valor 'NONE' es el último valor, que no funcionaría en este método. –

4

No es la forma en que están tratando, pero lo utiliza el método siguiente para hacer esto:

public static bool EnumTryParse<E>(string enumVal, out E resOut) 
     where E : struct 
{ 
     var enumValFxd = enumVal.Replace(' ', '_'); 
     if (Enum.IsDefined(typeof(E), enumValFxd)) 
     { 
      resOut = (E)Enum.Parse(typeof(E), 
      enumValFxd, true); 
      return true; 
     } 
     // ---------------------------------------- 
     foreach (var value in 
      Enum.GetNames(typeof (E)).Where(value => 
       value.Equals(enumValFxd, 
       StringComparison.OrdinalIgnoreCase))) 
     { 
      resOut = (E)Enum.Parse(typeof(E), value); 
      return true; 
     } 
     resOut = default(E); 
     return false; 
} 

No hay excepciones arrojado aquí ...

+1

Me encanta esta solución. Siempre prefiero un TryParse sobre la suposición de que los valores son legítimos. –

+0

+1 - Me gusta el patrón 'TryParse', pero una nota: al hacer la llamada al método' Enum.IsDefined' antes de intentar convertir, esto no podrá convertir representaciones de cadena del valor subyacente de un 'enum'. Ese es un beneficio del 'try catch' y luego verifica el algoritmo 'Enum.IsDefined'. Supongo que podrías hacer un 'int.TryParse' primero y agregar un caso especial para eso a la solución anterior. – jball

+0

@jball, por "representaciones de cadenas del valor subyacente", ¿estás hablando de "1", "12", "uno" o "dos" o "TwentyThree"? –

2

Me gustaría agregar en un parámetro defaultValue para una sobrecarga de mi TryParse para casos donde Quiero un valor predeterminado si no se puede analizar o si es nulo. Esto es más útil para analizar string.Empty o null.

Nota: esta implementación revertirá a defaultValue si se pasa un valor no deseado, por lo que es posible que desee modificarlo lanzando una excepción.

public static T TryParse<T>(string value, T defaultValue) where T: struct 
    { 
     if (string.IsNullOrWhiteSpace(value)) 
      { 
       return defaultValue; 
      } 

      T result; 
      if (Enum.TryParse<T>(value, out result)) 
      { 
       return result; 
      } 
      else 
      { 
       return defaultValue; // you may want to throw exception here 
      } 
     } 
    } 


    ConverterMode mode = EnumUtils<ConverterMode>.TryParse(stringValue, ConverterMode.DefaultMode); 
+1

Me encanta esta versión porque tengo que decirle qué Enum/valor devolver si falla, y no necesariamente un 0 u otro estándar que debo implementar en todas las enumeraciones . – RoLYroLLs

+0

No estoy muy seguro de por qué no lanzo una excepción donde indiqué aquí, pero creo que sería un mejor enfoque –

+0

en realidad lo que hice después de que 'Enum.TryParse' fuera para verificar si estaba definido con ' Enum.IsDefined() '. Si no fuera así, también lo convertí en el valor predeterminado. Y no me gustaría lanzar una excepción aquí porque es un "Try". ¿No crees? – RoLYroLLs

0

Sé que esto es viejo, pero en base a unas pocas muestras, he investigado junto con @Simon_Weaver's solución, esto es lo que tengo:

public static T TryParse(String value, T defaultValue) where T : struct { 
    if (String.IsNullOrWhiteSpace(value)) { 
     return defaultValue; 
    } 

    T result; 
    if (!Enum.TryParse(value, out result)) { 
     if (Enum.IsDefined(typeof (T), result) | result.ToString().Contains(",")) { 
      // do nothing 
     } else { 
      result = defaultValue; 
     } 
    } else { 
     result = defaultValue; 
    } 

    return result; 
}
Cuestiones relacionadas