解析枚举跳过已过时

时间:2017-03-13 07:57:59

标签: c# generics enums

当我将int值转换为枚举时,如何跳过过时的值?我在下面有最低限度的工作示例:

using System;

public class Program
{
    public static void Main()
    {
        int valueInt = 1;
        var en = (TestObsolete)valueInt;
        Console.WriteLine(en);
    }
}

enum TestObsolete
{
    Undefined,
    [Obsolete]
    ValueA = 1,
    ValueB=1,
}

我正在获得ValueA,但期望获得ValueB。特别是我对以下签名的通用方法感兴趣:

public static T ParseEnumWithoutObsolete<T>(int val) where T: struct {

我试着这样做:

T @enum;
var enumValues = Enum.GetValues(typeof(T)).Cast<T>();
var obsoleteValues = enumValues.Where(a => typeof(T).GetField(a.ToString()).CustomAttributes.Any(t => t is ObsoleteAttribute));
var activeValues = enumValues.Except(obsoleteValues);

但坚持下一步。

1 个答案:

答案 0 :(得分:5)

  

我正在获得ValueA,但期望获得ValueB。

你得到整数1所代表的值。你看到那个ValueA的事实与Parse无关,而且一切都是做ToString

记住,当你有一个枚举类型的值时,它真的非常重要,它实际上只是一个整数。对于相同的整数值,可以有多个名称,当您获得该值时,它们完全无法区分。

听起来像你真正想做的事情 - 可能除了你的解析方法之外 - 就是写一个ToStringWithoutObsolete方法。这可以将值映射到名称,但仅适用于没有过时属性的值。请注意,在代码中的任何位置使用typeof(T).GetField(a.ToString())都会导致结果无法预测。最好在枚举类型中获取 all 静态字段。例如:

var valueToName = typeof(T)
    .GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static)
    .Where(f => !f.IsDefined(typeof(ObsoleteAttribute), false)
    .ToDictionary(f => (T) f.GetValue(null),
                  f => f.Name);