如何枚举枚举,跳过默认值

时间:2013-09-10 18:17:06

标签: .net enums

当我声明枚举时,我经常添加一个NOT_SET = 0值来知道实例何时尚未初始化。当我枚举这样一个枚举的值时(如herehere所述),丢弃NOT_SET值的最佳方法是什么?我能想到的最好的是

Enum.GetValues(typeof(T)).Cast<int>().Where(item => (0 != (int)item)).Cast<T>();

我不喜欢它,因为所有Cast&lt;&gt;的迭代次数过多。我更喜欢基于

的东西
(T[]) Enum.GetValues(typeof(T))

没有所有Cast&lt;&gt ;.

3 个答案:

答案 0 :(得分:5)

不清楚为什么你还有两个 Cast<T>来电,但这很容易分两步完成:

var allValues = (T[]) Enum.GetValues(typeof(T));
var allButDefault = allValues.Except(Enumerable.Repeat(default(T), 1));

在这里使用Except可以避免装箱,假设默认比较器做正确的事情。请注意,它需要构建一个集合,因此可能最好使用我的原始代码:

var allValues = (T[]) Enum.GetValues(typeof(T));
var allButDefault = allValues.Where(t => !t.Equals(default(T)));

或者使用T的默认相等比较器:

var allValues = (T[]) Enum.GetValues(typeof(T));
var comparer = EqualityComparer<T>.Default;
var allButDefault = allValues.Where(t => !comparer.Equals(t, default(T)));

请注意,所有这些都会处理非基于int的枚举。

您可能还想查看我的Unconstrained Melody项目,该项目建立在实际约束T为枚举的基础上。

您可以使用各种选项来提高性能,避免每次都创建阵列等。我们不知道这段代码的性能如何,所以我没有在这里详细介绍

答案 1 :(得分:1)

您如何区分这些案例:

  • 枚举,其default(T)已声明未知未设置标签:public enum Foo { Unknown = 0 , Alpha = 1 , Bravo = 2 , Charlie = 3 , }

  • 没有为其default(T)定义标签的枚举:
    ``public enum Bar {Alpha = 1,Bravo = 2,Charlie = 3,}

  • 带有为其default(T)定义标签的枚举,但该标签代表实际有效值?
    public enum FooBar { Alpha = 0 , Bravo = 1, Charlie = 2 , }

  • [Flags]枚举,其中没有设置位有意义:
    [Flags] public enum ErrorConditions { None = 0x0000 , ErrorState_X = 0x0001 , ErrorState_Y = 0x0002 , ErrorState_Z = 0x0004 , ErrorState_XY = 0x0003 , ... }

在我看来,如果不知道所讨论的枚举的潜在语义,你就不能做你想做的事情,最终不会在脚下射击。

答案 2 :(得分:1)

  

我不喜欢它,因为所有Cast&lt;&gt;的迭代次数过多。

您的陈述表明您误解了正在发生的事情。您会发现,如果您下载源代码并启用.NET Framework源步进,那么您提到的“所有迭代”就不会发生。 LINQ将您的表达式转换为单个循环。

当然,这是一个比你自己写的更复杂的循环,但肯定不是创建一个整数集合,然后创建一个枚举集合。

相关问题