恕我直言,标记为答案的帖子不正确。
参数和数据验证是我几十年前钻研的事情之一。
为什么
验证是必需的,因为基本上任何整数值都可以分配给枚举而不会引发错误。
我花了很多天研究 C# 枚举验证,因为它在很多情况下都是必要的功能。
在哪里
对我来说,枚举验证的主要目的是验证从文件中读取的数据:您永远不知道文件是否已损坏、是否被外部修改或被故意入侵。
并且对从剪贴板粘贴的应用程序数据进行枚举验证:您永远不知道用户是否编辑了剪贴板内容。
也就是说,我花了几天时间研究和测试许多方法,包括分析我能找到或设计的每种方法的性能。
调用 System.Enum 中的任何内容都非常慢,以至于对于包含成百上千个对象的函数来说,这些对象的属性中具有一个或多个必须验证边界的枚举,这会导致明显的性能损失。
最重要的是,在验证枚举值时远离 System.Enum 类中的所有内容,它非常慢。
结果
我目前用于枚举验证的方法可能会引起这里许多程序员的翻白眼,但恕我直言,对于我的特定应用程序设计而言,它是最不邪恶的。
我定义了一个或两个常量,它们是枚举的上限和(可选)下限,并在一对 if() 语句中使用它们进行验证。
一个缺点是,如果您更改枚举,您必须确保更新常量。
此方法也仅在枚举是“自动”样式时才有效,其中每个枚举元素都是增量整数值,例如 0,1,2,3,4,.... 它不能与标志或枚举一起正常工作具有非增量值。
另请注意,此方法几乎与常规 int32 上的 "" 一样快(在我的测试中获得了 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 个滴答 = 10ns。
注意这里的代码不是完整的测试代码,它只是基本的枚举验证方法。还测试了许多其他变体,所有变体的结果都与此处显示的 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 滴答
注意:此代码版本不会限制到最小值/最大值,但如果超出范围则返回默认值。
public static T ValidateItem<T>(T eEnumItem)
{
if (Enum.IsDefined(typeof(T), eEnumItem) == true)
return eEnumItem;
else
return default(T);
}
System.Enum Convert Int32 with casts = 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-