11

How can I check if an enum if marked as obsolete?

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

Now at runtime, I need to know which ones are obsolete:

foreach (var myEnum in Enum.GetValues(typeof(MyEnums)).Cast<MyEnums>())
{
    // How can I check if myEnum is obsolete?
}
John Saunders
  • 160,644
  • 26
  • 247
  • 397
Drake
  • 2,679
  • 4
  • 45
  • 88
  • 2
    What do you mean exactly? Apart from looking at the source code and searching for usages? Do you want to know if it's obsolete at runtime? Could reflection help there? If so, this might help: http://stackoverflow.com/questions/1799370/getting-attributes-of-enums-value –  Apr 23 '15 at 19:25

5 Answers5

25

The following method checks whether an enum value has the Obsolete attribute:

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);
}

You can use it like this:

var isObsolete2 = IsObsolete(MyEnums.MyEnum2); // returns true
var isObsolete3 = IsObsolete(MyEnums.MyEnum3); // returns false
M4N
  • 94,805
  • 45
  • 217
  • 260
  • If there are multiple enums with the same value, it won't work. You'll have to work on `GetNames()` instead of `GetValues()` – xanatos Apr 23 '15 at 19:41
6

Here is a very clean extension method. The trick is that you are reflecting on a field off of the enum's type using the enum's name.

   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));
   }
jbtule
  • 31,383
  • 12
  • 95
  • 128
2

You can, but you'll need to use reflection:

bool hasIt = typeof (MyEnums).GetField("MyEnum2")
                .GetCustomAttribute(typeof (ObsoleteAttribute)) != null;

In the other hand, you can get all obsolete enum fields using some LINQ:

IEnumerable<FieldInfo> obsoleteEnumValueFields = typeof (MyEnums)
              .GetFields(BindingFlags.Public | BindingFlags.Static)
              .Where(fieldInfo => fieldInfo.GetCustomAttribute(typeof (ObsoleteAttribute)) != null);

And finally, using above result, you can get all obsolete enum values!

IEnumerable<MyEnums> obsoleteEnumValues = obsoleteEnumValueFields
                                .Select(fieldInfo => (MyEnums)fieldInfo.GetValue(null));
Matías Fidemraizer
  • 63,804
  • 18
  • 124
  • 206
1

Thanks @M4N here's an extension method approach of your solution:

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);
}

Call it like this:

bool isObsolete2 = MyEnums.MyEnum2.IsObsolete(); // true
bool isObsolete3 = MyEnums.MyEnum3.IsObsolete(); // false
v01pe
  • 1,096
  • 2
  • 11
  • 19
0

I just made this utils class for handling this:

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();
    }
}

And the corresponding unittest (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
    }
Stephan Møller
  • 1,247
  • 19
  • 39