ИМХО пост, помеченный как ответ неверный.
Проверка параметров и данных - одна из тех вещей, которые были изучены мной десятилетия назад.
ПОЧЕМУ
Требуется валидация, потому что по существу любое целочисленное значение может быть присвоено перечислению без выдачи ошибки.
Я потратил много дней на исследование валидации C #, потому что во многих случаях это необходимая функция.
WHERE
Основная цель проверки перечисления для меня заключается в проверке данных, считанных из файла: вы никогда не узнаете, был ли файл поврежден или был изменен извне, или был специально взломан.
И с проверкой перечисления данных приложения, вставленных из буфера обмена: вы никогда не узнаете, редактировал ли пользователь содержимое буфера обмена.
Тем не менее, я потратил несколько дней на исследование и тестирование многих методов, включая анализ производительности каждого метода, который я смог найти или спроектировать.
Выполнение вызовов во что-либо в System.Enum было настолько медленным, что это было заметное снижение производительности для функций, которые содержали сотни или тысячи объектов с одним или несколькими перечислениями в своих свойствах, которые должны были проверяться для границ.
Итог, держитесь подальше от всего в классе System.Enum при проверке значений перечисления, это ужасно медленно.
РЕЗУЛЬТАТ
Метод, который я в настоящее время использую для проверки перечисления, вероятно, привлечет внимание многих программистов, но это - наименьшее зло для моего конкретного приложения.
Я определяю одну или две константы, которые являются верхними и (необязательно) нижними границами перечисления, и использую их в паре операторов if () для проверки.
Недостатком является то, что вы должны быть уверены, что обновите константы, если вы измените перечисление.
Этот метод также работает только в том случае, если перечисление является стилем «auto», где каждый элемент перечисления является инкрементным целочисленным значением, таким как 0,1,2,3,4, .... Он не будет работать должным образом с флагами или перечислениями, которые имеют значения, которые не являются инкрементными.
Также обратите внимание, что этот метод почти такой же быстрый, как и обычный, если "<" ">" на обычных int32s (которые набрали 38 000 тиков в моих тестах).
Например:
public const MyEnum MYENUM_MINIMUM = MyEnum.One;
public const MyEnum MYENUM_MAXIMUM = MyEnum.Four;
public enum MyEnum
{
One,
Two,
Three,
Four
};
public static MyEnum Validate(MyEnum value)
{
if (value < MYENUM_MINIMUM) { return MYENUM_MINIMUM; }
if (value > MYENUM_MAXIMUM) { return MYENUM_MAXIMUM; }
return value;
}
ПРОИЗВОДИТЕЛЬНОСТЬ
Для тех, кто заинтересован, я описал следующие варианты проверки перечисления, и вот результаты.
Профилирование выполнялось при компиляции релиза в цикле по миллиону раз для каждого метода со случайным целочисленным входным значением. Каждый тест проводился более 10 раз и усреднялся. Тиковые результаты включают в себя общее время выполнения, которое будет включать генерацию случайных чисел и т. Д., Но они будут постоянными по всем тестам. 1 галочка = 10 нс.
Обратите внимание, что код здесь не является полным тестовым кодом, это всего лишь основной метод проверки перечисления. Было также много дополнительных вариаций, которые были протестированы, и все они с результатами, подобными показанным здесь, которые принесли 1 800 000 тиков.
Перечислены от медленного к быстрому с округленными результатами, надеюсь, без опечаток.
Границы, определенные в методе = 13 600 000 тиков
public static T Clamp<T>(T value)
{
int minimum = Enum.GetValues(typeof(T)).GetLowerBound(0);
int maximum = Enum.GetValues(typeof(T)).GetUpperBound(0);
if (Convert.ToInt32(value) < minimum) { return (T)Enum.ToObject(typeof(T), minimum); }
if (Convert.ToInt32(value) > maximum) { return (T)Enum.ToObject(typeof(T), maximum); }
return value;
}
Enum.IsDefined = 1 800 000 тиков
Примечание: эта версия кода не ограничивается Min / Max, но возвращает Default, если выходит за пределы.
public static T ValidateItem<T>(T eEnumItem)
{
if (Enum.IsDefined(typeof(T), eEnumItem) == true)
return eEnumItem;
else
return default(T);
}
System.Enum Convert Int32 с приведениями = 1 800 000 тиков
public static Enum Clamp(this Enum value, Enum minimum, Enum maximum)
{
if (Convert.ToInt32(value) < Convert.ToInt32(minimum)) { return minimum; }
if (Convert.ToInt32(value) > Convert.ToInt32(maximum)) { return maximum; }
return value;
}
if () Мин. / Макс. Константы = 43 000 тиков = победитель в 42 раза и в 316 раз быстрее.
public static MyEnum Clamp(MyEnum value)
{
if (value < MYENUM_MINIMUM) { return MYENUM_MINIMUM; }
if (value > MYENUM_MAXIMUM) { return MYENUM_MAXIMUM; }
return value;
}
-eol-