2010-10-06 25 views
10

Załóżmy ENUM:Generic ciąg ENUM konwersji

public enum SysLogsAppTypes { None, MonitorService, MonitorTool }; 

i tutaj jest funkcja konwersji z powrotem do reprezentacji ToString()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; 
    } 
} 

Czy istnieje sposób, aby ten Generic ??

Próbowałem:

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; 
    } 
} 

ale otrzymuję: 'T' jest 'parametr typ', który nie jest ważny w danym kontekście
gdzie istnieje T.None

Wszelkie Wsparcie ? Dzięki

+2

Wystarczy zastąpić domyślną '(T) dla' 'T.None' i jesteś gotowy do pracy. – thecoop

Odpowiedz

10

Myślę, że kluczowe default jest to, czego potrzebujesz:

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

To jest poprawna odpowiedź, ale ważne jest, aby pamiętać, że "domyślne" wyliczenie jest dowolną wartością reprezentowaną przez 0. Jest to zwykle pierwsza wartość. Jednakże jeśli twoje wyliczenie zaczyna się od 1, zwrócisz '0' zamiast jakiejkolwiek wartości prawnej w wyliczeniu. Użycie tej metody wymagałoby zastrzeżenia dla tego zachowania lub jakiegoś standardu kodowania. Na przykład widziałem niektóre wyliczenia, gdzie wartość "NONE" jest ostatnią wartością, która nie działałaby w tej metodzie. –

4

Nie sposób próbujesz go, ale używam metody poniżej, aby to zrobić:

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; 
} 

żadnych wyjątków wyrzucony tutaj ...

+1

Uwielbiam to rozwiązanie. Zawsze wolę TryParse od założenia, że ​​wartości są uzasadnione. –

+0

+1 - Podoba mi się wzór 'TryParse', ale uwaga: wykonując wywołanie metody' Enum.IsDefined' przed próbą konwertowania, nie uda się przekonwertować reprezentacji łańcuchowej wartości bazowej 'enum'. To jedna zaleta 'try catch ', a następnie sprawdź algorytm' Enum.IsDefined'. Przypuszczam, że możesz zrobić najpierw 'int.TryParse' i dodać specjalny przypadek do powyższego rozwiązania. – jball

+0

@jball, przez "ciąg reprezentacji wartości podstawowej", czy mówisz o "1", "12", "jeden" lub "dwa" lub "Dwadzieścia trzy"? –

2

Chciałbym dodać parametr defaultValue dla przeciążenia mojego TryParse dla przypadków, w których Chcę wartość domyślną, jeśli nie można jej przeanalizować lub ma wartość null. Jest to najbardziej przydatne do analizowania string.Empty lub null.

Uwaga: ta implementacja powróci do defaultValue, jeśli zostanie przekazana wartość śmieciowa - więc możesz ją poprawić, rzucając wyjątek.

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

Uwielbiam tę wersję, ponieważ dostaję, aby powiedzieć, co Enum/wartość do zwrotu, jeśli zawiedzie, i niekoniecznie 0 lub inny standard muszę wdrożyć we wszystkich enums . – RoLYroLLs

+0

Nie jestem do końca pewien, dlaczego nie wyrzucam wyjątku tam, gdzie zaznaczyłem, ale uważam, że byłoby to lepsze podejście. –

+0

faktycznie to, co zrobiłem po "Enum.TryParse" było sprawdzenie, czy zostało zdefiniowane z ' Enum.IsDefined() '. Jeśli nie, to ja również ustawiłem wartość domyślną. I nie chciałbym tu rzucić wyjątku, ponieważ jest to "Try". Nie sądzisz? – RoLYroLLs

0

wiem, że to jest stary, ale na podstawie kilku próbek, mam zbadane wraz z @Simon_Weaver's rozwiązania jest to, co mam:

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; 
}