检查枚举是否已过时。

11

我该如何检查一个枚举(enum)是否被标记为废弃?

public enum MyEnums
{
    MyEnum1,
    [Obsolete("How can you know that I'm obsolete?")]
    MyEnum2,
    MyEnum3
}

现在在运行时,我需要知道哪些是过时的:

foreach (var myEnum in Enum.GetValues(typeof(MyEnums)).Cast<MyEnums>())
{
    // How can I check if myEnum is obsolete?
}

2
你的意思是什么?除了查看源代码和搜索用法之外,你还想知道它是否在运行时过时吗?反射能帮助吗?如果可以的话,这可能会有所帮助:https://dev59.com/CnI-5IYBdhLWcg3wipBk - user4410678
我更新了我的问题。 - Drake
5个回答

阿里云服务器只需要99元/年,新老用户同享,点击查看详情
25
以下方法检查枚举值是否具有 Obsolete 属性:
public static bool IsObsolete(Enum value)
{
    var fi = value.GetType().GetField(value.ToString());
    var attributes = (ObsoleteAttribute[])
        fi.GetCustomAttributes(typeof(ObsoleteAttribute), false);
    return (attributes != null && attributes.Length > 0);
}

您可以像这样使用它:

var isObsolete2 = IsObsolete(MyEnums.MyEnum2); // returns true
var isObsolete3 = IsObsolete(MyEnums.MyEnum3); // returns false

如果有多个枚举具有相同的值,它将无法工作。您必须使用GetNames()而不是GetValues()来解决问题。 - xanatos

6

这是一个非常简洁的扩展方法。关键在于使用枚举的名称,反射枚举类型中的字段。

   public static bool IsObsolete(this Enum value)
   {  
      var enumType = value.GetType();
      var enumName = enumType.GetEnumName(value);
      var fieldInfo = enumType.GetField(enumName);
      return Attribute.IsDefined(fieldInfo, typeof(ObsoleteAttribute));
   }

2
您可以这样做,但需要使用反射技术
bool hasIt = typeof (MyEnums).GetField("MyEnum2")
                .GetCustomAttribute(typeof (ObsoleteAttribute)) != null;
另一方面,您可以使用一些LINQ获取所有已过时的枚举字段:
IEnumerable<FieldInfo> obsoleteEnumValueFields = typeof (MyEnums)
              .GetFields(BindingFlags.Public | BindingFlags.Static)
              .Where(fieldInfo => fieldInfo.GetCustomAttribute(typeof (ObsoleteAttribute)) != null);
最后,使用上述结果,您可以获取所有已过时的枚举值!
IEnumerable<MyEnums> obsoleteEnumValues = obsoleteEnumValueFields
                                .Select(fieldInfo => (MyEnums)fieldInfo.GetValue(null));

1

感谢 @M4N,这是您解决方案的扩展方法:

public static bool IsObsolete(this Enum value)
{
    FieldInfo fieldInfo = value.GetType().GetField(value.ToString());
    ObsoleteAttribute[] attributes = (ObsoleteAttribute[])fieldInfo.GetCustomAttributes(typeof(ObsoleteAttribute), false);
    return (attributes != null && attributes.Length > 0);
}
像这样调用它:
bool isObsolete2 = MyEnums.MyEnum2.IsObsolete(); // true
bool isObsolete3 = MyEnums.MyEnum3.IsObsolete(); // false

0
我刚刚为处理这个问题创建了这个工具类:
public static class EnumUtils
{
    public static bool IsObsolete<TEnumType>(TEnumType value) where TEnumType : struct
    {
        var fi = value.GetType().GetField(value.ToString());
        var attributes = (ObsoleteAttribute[])
            fi.GetCustomAttributes(typeof(ObsoleteAttribute), false);
        return (attributes != null && attributes.Length > 0);
    }

    public static List<TEnumType> GetObsoleteValues<TEnumType>() where TEnumType : struct
    {
        return GetAllValues<TEnumType>().Where(e => IsObsolete(e)).ToList();
    }

    public static List<TEnumType> GetNonObsoleteValues<TEnumType>() where TEnumType : struct
    {
        return GetAllValues<TEnumType>().Where(e => !IsObsolete(e)).ToList();
    }

    public static List<TEnumType> GetAllValues<TEnumType>() where TEnumType : struct
    {
        return Enum.GetValues(typeof(TEnumType)).Cast<TEnumType>().ToList();
    }
}

对应的单元测试(MSTest)如下:

    [TestClass]
    public class EnumUtilsTest : UnitTestBase
    {
        #pragma warning disable CS0612 // Type or member is obsolete

        [TestMethod]
        public void GetAllValues_Test()
        {
            var values = EnumUtils.GetAllValues<UnitTestEnumValues>();
            Assert.AreEqual(4, values.Count);
            Assert.AreEqual(UnitTestEnumValues.A, values[0]);
            Assert.AreEqual(UnitTestEnumValues.B_Obsolete, values[1]);
            Assert.AreEqual(UnitTestEnumValues.C, values[2]);
            Assert.AreEqual(UnitTestEnumValues.D_Obsolete, values[3]);
        }

        [TestMethod]
        public void GetObsoleteValues_Test()
        {
            var values = EnumUtils.GetObsoleteValues<UnitTestEnumValues>();
            Assert.AreEqual(2, values.Count);
            Assert.AreEqual(UnitTestEnumValues.B_Obsolete, values[0]);
            Assert.AreEqual(UnitTestEnumValues.D_Obsolete, values[1]);
        }

        [TestMethod]
        public void GetNonObsoleteValues_Test()
        {
            var values = EnumUtils.GetNonObsoleteValues<UnitTestEnumValues>();
            Assert.AreEqual(2, values.Count);
            Assert.AreEqual(UnitTestEnumValues.A, values[0]);
            Assert.AreEqual(UnitTestEnumValues.C, values[1]);
        }

        [TestMethod]
        public void IsObsolete_Test()
        {
            Assert.AreEqual(false, EnumUtils.IsObsolete(UnitTestEnumValues.A));
            Assert.AreEqual(true, EnumUtils.IsObsolete(UnitTestEnumValues.B_Obsolete));
            Assert.AreEqual(false, EnumUtils.IsObsolete(UnitTestEnumValues.C));
            Assert.AreEqual(true, EnumUtils.IsObsolete(UnitTestEnumValues.D_Obsolete));
        }

        public enum UnitTestEnumValues
        {
            A,
            [Obsolete]
            B_Obsolete,
            C,
            [Obsolete]
            D_Obsolete
        }

        #pragma warning restore CS0612 // Type or member is obsolete
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,