Przeczytałem kilka postów SO i wydaje się, że brakuje najbardziej podstawowej operacji.
public enum LoggingLevel
{
Off = 0,
Error = 1,
Warning = 2,
Info = 3,
Debug = 4,
Trace = 5
};
if (s == "LogLevel")
{
_log.LogLevel = (LoggingLevel)Convert.ToInt32("78");
_log.LogLevel = (LoggingLevel)Enum.Parse(typeof(LoggingLevel), "78");
_log.WriteDebug(_log.LogLevel.ToString());
}
To nie powoduje wyjątków, chętnie przechowuje 78
. Czy istnieje sposób na walidację wartości przechodzącej do wyliczenia?
Odpowiedzi:
Sprawdź Enum.IsDefined
Stosowanie:
Oto przykład z tej strony:
Przykład wyświetla następujące dane wyjściowe:
źródło
LoggingLevel
używaną jako pamięć, a następnie przedstaw ją jakoLoggingLevel
wartość wyliczoną.IsDefined
to, że nie działa to dla członków wyliczenia bitwised.Powyższe rozwiązania nie dotyczą
[Flags]
sytuacji.Poniższe rozwiązanie może mieć pewne problemy z wydajnością (jestem pewien, że można je zoptymalizować na różne sposoby), ale zasadniczo zawsze wykaże, czy wartość wyliczenia jest prawidłowa, czy nie .
Opiera się na trzech założeniach:
int
, absolutnie niczym innym-
Wywołanie
ToString()
wyliczenia zwracaint
wartość, jeśli żadne wyliczenie (flaga lub nie) nie jest dopasowane. Jeśli dopasowana zostanie dozwolona wartość wyliczenia, wypisze nazwę dopasowania (-ów).Więc:
Mając na uwadze te dwie reguły, możemy założyć, że jeśli .NET Framework wykonuje swoje zadanie poprawnie, to każde wywołanie prawidłowej
ToString()
metody wyliczenia spowoduje powstanie czegoś, co ma znak alfabetu jako pierwszy znak:Można to nazwać „włamaniem”, ale korzyści są takie, że polegając na własnej implementacji Microsoft
Enum
i standardach C #, nie polegasz na własnym, potencjalnie błędnym kodzie lub sprawdzeniach. W sytuacjach, w których wydajność nie jest wyjątkowo krytyczna, pozwoli to zaoszczędzić wiele nieprzyjemnychswitch
stwierdzeń lub innych kontroli!Edytować
Podziękowania dla @ChaseMedallion za wskazanie, że moja oryginalna implementacja nie obsługiwała wartości ujemnych. Zostało to naprawione i zapewniono testy.
Oraz testy potwierdzające:
źródło
[Flags]
mają rozsądne wartości całkowite.Kanoniczna odpowiedź brzmiałaby
Enum.IsDefined
, ale to jest: trochę powolne, jeśli jest używane w ciasnej pętli, oraz b: nie jest przydatne w przypadku[Flags]
wyliczeń.Osobiście przestałbym się tym martwić i po prostu
switch
odpowiednio pamiętając:default:
(lub miej pustedefault:
wyjaśnienie dlaczego)default:
Tak jak to:
źródło
Posługiwać się:
źródło
Użyj Enum.IsDefined .
źródło
Aby sobie z tym poradzić
[Flags]
, możesz również skorzystać z tego rozwiązania z C # Cookbook :Najpierw dodaj nową
ALL
wartość do wyliczenia:Następnie sprawdź, czy wartość jest w
ALL
:źródło
Jednym ze sposobów byłoby poleganie na rzutowaniu i konwersji wyliczenia na ciąg. Podczas rzutowania int na typ Enum int jest konwertowany na odpowiednią wartość wyliczenia lub wynikowe wyliczenie zawiera po prostu int jako wartość, jeśli wartość wyliczenia nie jest zdefiniowana dla int.
Nie testowane w żadnych skrajnych przypadkach.
źródło
Jak powiedzieli inni,
Enum.IsDefined
zwraca,false
nawet jeśli masz poprawną kombinację flag bitowych dla wyliczenia ozdobionego rozszerzeniemFlagsAttribute
.Niestety, jedyny sposób na utworzenie metody zwracającej wartość true dla prawidłowych flag bitowych jest trochę długi:
Możesz chcieć zapisać wyniki
GetCustomAttribute
w słowniku:Należy zauważyć, że powyższy kod używa nowego
Enum
ograniczenia,T
które jest dostępne tylko od wersji C # 7,3. Musisz zdaćobject value
w starszych wersjach i zadzwonićGetType()
do niego.źródło