2012-01-19 12 views
6

Mam metodę, która próbuje dopasować ciąg do DescriptionAttribute wartości wyliczeniowych, a następnie zwraca wartość wyliczenia. W przypadku, gdy mecz nie został znaleziony, należy zwrócić wartość domyślną, co uważałem, że może po prostu wrócić 0. Ale to nie zdarzy ...Zwraca domyślną wartość wyliczenia, gdy typ enum nie jest znany

private Enum GetEnumFromDescription(Type enumType, string description) 
{ 
     var enumValues = Enum.GetValues(enumType); 

     foreach (Enum e in enumValues) 
     { 
      if (string.Compare(description, GetDescription(e), true) == 0) 
        return e; 
     } 

     return 0; // not compiling 
} 

Jak należy kodować wyżej?

+0

Dlaczego nie przekazać parametru typu za pomocą generycznych? – millimoose

+0

Dlaczego oznaczono to za pomocą "iteratora" i "zwrotu zysku"? –

+0

@Interdial Czy mogę? mój enumType pochodzi z Type.GetReflectionOnlyType (somestringfromdatabase). – Jake

Odpowiedz

13

Można użyć

return (Enum) Activator.CreateInstance(enumType); 

To daje wartość domyślną dla danego typu - czyli to, co chcesz.

EDYCJA: Spodziewałem się, że znasz typ w czasie kompilacji, w którym to przypadku generics są dobrym podejściem. Chociaż wydaje się, że tak nie jest, pozostawiam resztę tej odpowiedzi na wypadek, gdyby był przydatny komuś innemu.

Alternatywnie, można użyć Unconstrained Melody który zawiera już coś podobnego tej funkcji w sposób bardziej efektywny, bezpieczny typ postaci :)

MyEnum value; 
if (Enums.TryParseDescription<MyEnum>(description, out value)) 
{ 
    // Parse successful 
} 

value zostanie ustawiony na wartość „0”, jeśli operacja ISN parse powodzenie.

Obecnie jest rozróżniana wielkość liter, ale można łatwo utworzyć wersję niewrażliwą na wielkość liter. (Albo daj mi znać, a ja mogę to zrobić.)

+0

Należy użyć 'Enum.ToObject (enumType, 0)'. – hazzik

+0

@hazzik: * Czy * może być? Dlaczego powinieneś*? Jak sądzisz, jaka jest jej przewaga nad podejściem, które zasugerowałem? Nie mówię, że to nie zadziała - tylko że istnieje więcej niż jedna rzecz, która zadziała, i jeśli masz zamiar twierdzić, że ktoś * powinien * stosować jedno podejście do drugiego, powinieneś to uzasadnić. –

+1

Nie jestem native speakerem i dla mnie nie ma dużej różnicy między tymi czasownikami modalnymi, więc przepraszam, jeśli kogoś uraziłem. Ale dla usprawiedliwienia, myślę, że to jest lepsze, ponieważ 'Activator.CreateInstance' jest ogólnym rozwiązaniem dla _all_ typów wartości, ale' Enum.ToObject' jest specyficzne dla wyliczeń. A także _prawdopodobnie_ działa szybciej niż aktywator. Ponadto, 'Enum.ToObject' jest używany wewnątrz' Enum.GetValues ​​(t) ' – hazzik

0

Może to będzie działać

return (Enum)enumValues[0]; 
+2

Nie, to nie zadziała, jeśli wyliczenie nie definiuje wartości odpowiadającej 0. Spowoduje to również wyrzucenie wyjątku, jeśli enum nie będzie 't define * any * values. –

+1

@JonSkeet hmm ... skąd znasz nawet najdrobniejsze szczegóły z głowy? Z pewnością nie jest to coś, co dzieje się regularnie? – Jake

+0

@Jon nie rozumiem, dlaczego to nie zadziała. Po prostu pobiera pierwszy element z tablicy. – clearpath

1

wierzę, że prawidłowe podejście jest

(Enum)Enum.ToObject(enumType, 0) 

Ponieważ

  • Activator.CreateInstance jest ogólne rozwiązanie dla wszystkich typów wartości i Enum.ToObject jest specyficznym rozwiązaniem dla wyliczeń, więc Enum.ToObject de jasne zamierzenia kodeksu.
  • Enum.ToObjectprawdopodobnie działa szybciej niż Activator.CreateInstance
  • Enum.ToObject jest używany wewnątrz Enum.GetValues do pobrania wartości.
Powiązane problemy