54

In vs2008, is it possible to write an extension methods which would apply to any enumeration.

I know you can write extension methods against a specific enumeration, but I want to be able to every enumeration using a single extension method. Is this possible?

Eric Haskins
  • 8,505
  • 12
  • 38
  • 47
  • Does this answer your question? [Extension method on enumeration, not instance of enumeration](https://stackoverflow.com/questions/2422113/extension-method-on-enumeration-not-instance-of-enumeration) – malat Feb 11 '20 at 09:22

7 Answers7

81

Yes, just code against the base Enum type, e.g.

public static void Something(this Enum e)
{
    // code here
}

The down-side is you'll probably end up doing some quite nasty stuff like finding the real base type using Enum.GetUnderlyingType, casting, and going down different branches depending on what the base type of the enum is, but you can find some good uses for it (e.g. we have IsOneOf and IsCombinationOf methods that apply to all enums).

PS: Remember when writing the method that, although ill advised, you can use float and double as the base types for enums so you'll need some special cases for those as well as unsigned values.

Greg Beech
  • 133,383
  • 43
  • 204
  • 250
  • The examples you gave are exactly what I want to do, even the same name. :) – Eric Haskins Nov 09 '08 at 22:43
  • 4
    @Greg: In which language can you use float and double as the underlying type for an enum? You can't in C# - you get error CS1008: Type byte, sbyte, short, ushort, int, uint, long, or ulong expected – Jon Skeet Nov 09 '08 at 23:01
  • 3
    The only language I know of that supports it is CIL. I haven't actually tried it out to prove it because it seems like a generally bad idea, but see Rico's comment near the bottom here: http://en.csharp-online.net/.NET_Type_Design_Guidelines%E2%80%94Enum_Design – Greg Beech Nov 10 '08 at 02:42
  • @Luis - No, you need C# 3.0 syntax for extension methods, which isn't supported in VS2005. – Greg Beech Jan 17 '09 at 15:19
  • @GregBeech: Are you able to help with this post? http://stackoverflow.com/q/18145161/175893 – Jimbo Aug 09 '13 at 12:13
18

FYI Here is a great example of an Enum Extension method that I have been able to use. It implements a case insensitive TryParse() function for enums:

public static class ExtensionMethods
{
    public static bool TryParse<T>(this Enum theEnum, string strType, 
        out T result)
    {
        string strTypeFixed = strType.Replace(' ', '_');
        if (Enum.IsDefined(typeof(T), strTypeFixed))
        {
            result = (T)Enum.Parse(typeof(T), strTypeFixed, true);
            return true;
        }
        else
        {
            foreach (string value in Enum.GetNames(typeof(T)))
            {
                if (value.Equals(strTypeFixed, 
                    StringComparison.OrdinalIgnoreCase))
                {
                    result = (T)Enum.Parse(typeof(T), value);
                    return true;
                }
            }
            result = default(T);
            return false;
        }
    }
}

You would use it in the following manner:

public enum TestEnum
{
    A,
    B,
    C
}

public void TestMethod(string StringOfEnum)
{
    TestEnum myEnum;
    myEnum.TryParse(StringOfEnum, out myEnum);
}

Here are the two sites that I visited to help come up with this code:

Case Insensitive TryParse for Enums

Extension methods for Enums

Leniel Maccaferri
  • 100,159
  • 46
  • 371
  • 480
Michael La Voie
  • 27,772
  • 14
  • 72
  • 92
  • 8
    Just as a footnote, from .net 4 onwards there's Enum.TryParse takes an overload to specify case sensitivity: http://msdn.microsoft.com/en-us/library/dd991317%28v=vs.100%29.aspx – KevD Sep 19 '12 at 13:12
18

Yes, you can. The target extenstion type is of type Enum. In C#, this would be done as:

public static void EnumExtension(this Enum e)
{
}

or like this in VB:

<Extension()> _
Public Sub EnumExtension(ByVal s As Enum)
End Sub
Scott Dorman
  • 42,236
  • 12
  • 79
  • 110
9

Here's another example - also nicer IMHO than having to create and initialize a temp variable.

public static class ExtensionMethods 
{
    public static void ForEach(this Enum enumType, Action<Enum> action)
    {
        foreach (var type in Enum.GetValues(enumType.GetType()))
        {
            action((Enum)type);
        }
    }
}

public enum TestEnum { A,B,C } 
public void TestMethod() 
{
    default(TestEnum).ForEach(Console.WriteLine); 
} 
Adriaan de Beer
  • 1,136
  • 13
  • 23
  • 1
    You are still creating a temporary instance of the enum in `default(TestEnum)`, albeit one that is anonymous and immediately up for garbage collection. It's worth pointing out that extension methods simply do not work without an instance of what is being extended, so the closest that we can get is to instantiate the Type of the enum itself and have an extension method off that type. See http://stackoverflow.com/questions/2422113/extension-method-on-enumeration-not-instance-of-enumeration for an interesting way of accomplishing this. – MushinNoShin Apr 22 '14 at 23:42
4

You can also implement conversion method as follows:

public static class Extensions
{
    public static ConvertType Convert<ConvertType>(this Enum e)
    {
        object o = null;
        Type type = typeof(ConvertType);

        if (type == typeof(int))
        {
            o = Convert.ToInt32(e);
        }
        else if (type == typeof(long))
        {
            o = Convert.ToInt64(e);
        }
        else if (type == typeof(short))
        {
            o = Convert.ToInt16(e);
        }
        else
        {
            o = Convert.ToString(e);
        }

        return (ConvertType)o;
    }
}

Here is an example usage:

int a = MyEnum.A.Convert<int>();
2

Sometimes there is a need to convert from one enum to another, based on the name or value of the enum. Here is how it can be done nicely with extension methods:

enum Enum1 { One = 1, Two = 2, Three = 3 };
enum Enum2 { Due = 2, Uno = 1 };
enum Enum3 { Two, One };

Enum2 e2 = Enum1.One.ConvertByValue<Enum2>();
Enum3 e3 = Enum1.One.ConvertByName<Enum3>();
Enum3 x2 = Enum1.Three.ConvertByValue<Enum3>();

public static class EnumConversionExtensions
{
    public static T ConvertByName<T>(this Enum value)
    {
        return (T)Enum.Parse(typeof(T), Enum.GetName(value.GetType(), value));
    }

    public static T ConvertByValue<T>(this Enum value)
    {
        return (T)((dynamic)((int)((object)value)));
    }
}
Esge
  • 180
  • 1
  • 8
1

Another example of making Enum extension - but this time it returns the input enum type.

public static IEnumerable<T> toElementsCollection<T>(this T value) where T : struct, IConvertible
    {
        if (typeof(T).IsEnum == false) throw new Exception("typeof(T).IsEnum == false");

        return Enum.GetValues(typeof(T)).Cast<T>();
    }

Example of usage:

public enum TestEnum { A,B,C };

TestEnum.A.toElementsCollection();
Bronek
  • 10,722
  • 2
  • 45
  • 46