Я прочитал несколько SO сообщений, и кажется, что основная работа отсутствует.
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());
}
Это не вызывает никаких исключений, он счастлив хранить 78
. Есть ли способ проверить значение, входящее в перечисление?
Ответы:
Проверьте Enum.IsDefined
Использование:
Вот пример с этой страницы:
В примере показан следующий вывод:
источник
LoggingLevel
используемое в качестве хранилища, а затем представить его какLoggingLevel
значение перечисления.IsDefined
это не работает для заумных членов enum.Вышеуказанные решения не имеют отношения к
[Flags]
ситуациям.Мое решение ниже может иметь некоторые проблемы с производительностью (я уверен, что можно оптимизировать различными способами), но по сути это всегда будет доказывать, является ли значение перечисления действительным или нет .
Он опирается на три предположения:
int
, абсолютно ничем иным-
Вызов
ToString()
enum возвращает либоint
значение, если enum (флаг или нет) не найден. Если допустимое значение перечисления совпадает, будет напечатано имя совпадения.Так:
Имея в виду эти два правила, мы можем предположить, что если .NET Framework выполнит свою работу правильно, то любые вызовы допустимого
ToString()
метода enum приведут к чему-то, что в качестве первого символа будет иметь буквенный символ:Можно было бы назвать это «взломом», но преимущества в том, что полагаясь на собственную реализацию Microsoft
Enum
и стандарты C #, вы не полагаетесь на свой собственный потенциально ошибочный код или проверки. В ситуациях, когда производительность не является исключительно критической, это сэкономит много неприятныхswitch
утверждений или других проверок!редактировать
Спасибо @ChaseMedallion за указание на то, что моя первоначальная реализация не поддерживала отрицательные значения. Это было исправлено и проведены тесты.
И тесты, чтобы поддержать это:
источник
[Flags]
имеют разумные целочисленные значения.Канонический ответ был бы
Enum.IsDefined
, но это: немного медленнее, если используется в узком цикле, и b: бесполезно для[Flags]
перечислений.Лично я перестал бы беспокоиться об этом и просто
switch
уместно вспомнить:default:
(или не пустыеdefault:
объясните почему)default:
Вот так:
источник
Использование:
источник
Используйте Enum.IsDefined .
источник
Чтобы справиться с этим,
[Flags]
вы также можете использовать это решение из C # Cookbook :Сначала добавьте новое
ALL
значение в ваше перечисление:Затем проверьте, находится ли значение в
ALL
:источник
Один из способов сделать это - полагаться на приведение и преобразование перечисления в строку. При приведении int к типу Enum int либо преобразуется в соответствующее значение перечисления, либо результирующее перечисление просто содержит int в качестве значения, если значение перечисления не определено для int.
Не проверено для любых крайних случаев.
источник
Как сказали другие,
Enum.IsDefined
возвращается,false
даже если у вас есть допустимая комбинация битовых флагов для перечисления, украшенного символомFlagsAttribute
.К сожалению, единственный способ создать метод, возвращающий true для допустимых битовых флагов, это немного длинно:
Вы можете кэшировать результаты
GetCustomAttribute
в словаре:Обратите внимание, что приведенный выше код использует новое
Enum
ограничение,T
доступное только с C # 7.3. Вам нужно передатьobject value
в старых версиях и позвонитьGetType()
по нему.источник