首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >验证枚举值

验证枚举值
EN

Stack Overflow用户
提问于 2008-08-17 13:14:43
回答 11查看 70K关注 0票数 83

我需要验证一个整数,以确定它是否是有效的枚举值。

在C#中实现这一点的最佳方法是什么?

EN

回答 11

Stack Overflow用户

回答已采纳

发布于 2011-01-27 01:02:45

你一定会喜欢这些人,他们认为数据不仅来自用户界面,而且来自你控制的用户界面!

IsDefined适用于大多数场景,您可以从以下开始:

代码语言:javascript
复制
public static bool TryParseEnum<TEnum>(this int enumValue, out TEnum retVal)
{
 retVal = default(TEnum);
 bool success = Enum.IsDefined(typeof(TEnum), enumValue);
 if (success)
 {
  retVal = (TEnum)Enum.ToObject(typeof(TEnum), enumValue);
 }
 return success;
}

(显然,如果你不认为‘this’是一个合适的int扩展,那就去掉它吧)

票数 95
EN

Stack Overflow用户

发布于 2013-04-02 06:03:57

我的帖子被标记为答案是错误的。

参数和数据验证是我几十年前学到的东西之一。

为什么选择

验证是必需的,因为基本上任何整数值都可以分配给枚举,而不会抛出错误。

我花了很多时间研究C#枚举验证,因为它在许多情况下是一个必要的函数。

所在的

对我来说,枚举验证的主要目的是验证从文件读取的数据:您永远不会知道文件是否已损坏、是否已被外部修改或是否被故意黑客攻击。

使用从剪贴板粘贴的应用程序数据的枚举验证:您永远不会知道用户是否编辑了剪贴板内容。

也就是说,我花了几天的时间研究和测试许多方法,包括分析我能找到或设计的每种方法的性能。

在System.Enum中调用任何东西都是如此之慢,以至于对于包含成百上千个对象的函数来说,这是一个明显的性能损失,这些对象的属性中有一个或多个枚举,必须对边界进行验证。

底线是,在验证枚举值时远离System.Enum类中的所有东西,它非常慢。

结果

我目前用于枚举验证的方法可能会吸引许多程序员的注意,但对于我的特定应用程序设计来说,它是最小的缺点。

我定义了一个或两个常量作为枚举的上界和下界(可选),并在两个if()语句中使用它们进行验证。

一个缺点是,如果更改枚举,则必须确保更新常量。

仅当枚举是"auto“样式时,此方法才有效,其中每个枚举元素都是一个递增的整数值,例如0,1,2,3,4,...它不能与具有非增量值的标志或枚举一起正常工作。

还要注意的是,这种方法几乎和常规int32s上的if "<“">”一样快(在我的测试中,它获得了38,000个滴答)。

例如:

代码语言:javascript
复制
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;
}

PERFORMANCE

对于那些感兴趣的人,我分析了枚举验证的以下变体,以下是结果。

分析是在release compile上执行的,每个方法都有一个随机整数输入值,循环了一百万次。每个测试都运行了10次以上,并取了平均值。tick结果包括执行的总时间,这将包括随机数生成等,但这些将在测试中保持不变。1刻度=10。

注意,这里的代码不是完整的测试代码,它只是基本的枚举验证方法。还有许多其他的变种进行了测试,所有这些变种的结果都与这里显示的结果相似,这些变种减少了180万个刻度。

列出了从最慢到最快的四舍五入结果,希望没有拼写错误。

在方法中确定的界限= 13,600,000个滴答

代码语言:javascript
复制
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刻度

注意:此代码版本不会钳制到最小/最大值,但如果超出范围,则返回默认值。

代码语言:javascript
复制
public static T ValidateItem<T>(T eEnumItem)
{
    if (Enum.IsDefined(typeof(T), eEnumItem) == true)
        return eEnumItem;
    else
        return default(T);
}

System.Enum转换Int32,投射= 1,800,000刻度

代码语言:javascript
复制
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倍。

代码语言:javascript
复制
public static MyEnum Clamp(MyEnum value)
{
    if (value < MYENUM_MINIMUM) { return MYENUM_MINIMUM; }
    if (value > MYENUM_MAXIMUM) { return MYENUM_MAXIMUM; }
    return value;
}

-停产-

票数 26
EN

Stack Overflow用户

发布于 2014-12-05 06:16:47

正如其他人提到的,Enum.IsDefined很慢,如果它在循环中,你必须意识到这一点。

进行多个比较时,一种更快的方法是首先将值放入HashSet中。然后只需使用Contains检查该值是否有效,如下所示:

代码语言:javascript
复制
int userInput = 4;
// below, Enum.GetValues converts enum to array. We then convert the array to hashset.
HashSet<int> validVals = new HashSet<int>((int[])Enum.GetValues(typeof(MyEnum)));
// the following could be in a loop, or do multiple comparisons, etc.
if (validVals.Contains(userInput))
{
    // is valid
}
票数 14
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13615

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档