解析枚举跳过已过时

Geo*_*yev 1 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,
}
Run Code Online (Sandbox Code Playgroud)

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

public static T ParseEnumWithoutObsolete<T>(int val) where T: struct {
Run Code Online (Sandbox Code Playgroud)

我试着这样做:

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);
Run Code Online (Sandbox Code Playgroud)

但坚持下一步.

Jon*_*eet 5

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

你得到整数1所代表的值.事实上,你看到ValueA与之无关Parse,以及与之相关的一切ToString.

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

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

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);
Run Code Online (Sandbox Code Playgroud)