175

I have this Enum code:

enum Duration { Day, Week, Month };

Can I add a extension methods for this Enum?

user2110292
  • 3,637
  • 7
  • 22
  • 22
  • 1
    Have you seen this?http://stackoverflow.com/questions/2422113/extension-method-on-enumeration-not-instance-of-enumeration – badpanda Mar 13 '13 at 14:27
  • 1
    Also, this. http://stackoverflow.com/questions/276585/enumeration-extension-methods – badpanda Mar 13 '13 at 14:30
  • short answer, yes. In this specific case you might want to consider the use of `TimeSpan` – Jodrell Mar 13 '13 at 14:31
  • 2
    Using extension methods on an enum would make me feel dirty. Create a class to encapsulate what is needed. Keep an enum as simple as possible. If you need more logic associated with it, then create a Duration class that exposes day, week, month plus contains any other logic that would have been in the extension method. – Jason Evans Mar 13 '13 at 14:31
  • It's awful add an extension method to an enum, not a good practice, in my opinion. If you need something more sophisticated you should create a class. – Omar Mar 13 '13 at 14:41
  • If you just want a bit of display quickness to allow selection like "Press 1 for EnumValue1 Press 2 for EnumValue2..." none of these will work. – StingyJack May 14 '17 at 23:43
  • 3
    I like having enum extension methods for flag groups. I prefer in if clauses for instance `Day.IsWorkday()` over `(Day & Days.Workday) > 0` with `Days.Workday` defined as `Monday | Tuesday ... | Friday`. The former is more clear in my opinion and has exactly the latter implemented. – Sebastian Werk Jul 11 '18 at 07:42
  • Does this answer your question? [Methods inside enum in C#](https://stackoverflow.com/questions/5985661/methods-inside-enum-in-c-sharp) – malat Feb 11 '20 at 09:23

8 Answers8

155

According to this site:

Extension methods provide a way to write methods for existing classes in a way other people on your team might actually discover and use. Given that enums are classes like any other it shouldn’t be too surprising that you can extend them, like:

enum Duration { Day, Week, Month };

static class DurationExtensions 
{
  public static DateTime From(this Duration duration, DateTime dateTime) 
  {
    switch (duration) 
    {
      case Day:   return dateTime.AddDays(1);
      case Week:  return dateTime.AddDays(7);
      case Month: return dateTime.AddMonths(1);
      default:    throw new ArgumentOutOfRangeException("duration");
    }
  }
}

I think enums are not the best choice in general but at least this lets you centralize some of the switch/if handling and abstract them away a bit until you can do something better. Remember to check the values are in range too.

You can read more here at Microsft MSDN.

TPAKTOPA
  • 2,462
  • 1
  • 19
  • 26
One Man Crew
  • 9,420
  • 2
  • 42
  • 51
  • I believe the "enums are evil" comment is out of place but has a basis in reality. I do find that enums can be a problem is overused, as they sort of lock you in to certain contexts and behaviors. – Ed Schwehm Mar 13 '13 at 14:37
  • 1
    Enums in C# kind of suck because this compiles and runs: `Duration d = 0;` – Graham Mar 30 '16 at 15:32
  • 35
    `Given that enums are classes` no they aren't classes. – wingerse Sep 02 '17 at 18:17
  • 3
    I use this sort of extension only if it is about the enum directly, like days of the week and extension methods IsWeekday(), IsWeekendday(). But classes are meant to encapsulate behaviours, so if there are a lot or complicated behaviours to encapsulate, a class is probably better. If it's limited and basic, I personally find extensions on enums okay. As with most design decisions there are fuzzy boundaries between choices (IMO). It's worth noting that extensions can only be done on top level static classes, not nested classes. If your enum is part of a class you'll need to make a class. – FreeText Oct 22 '19 at 14:45
  • 8
    @WingerSendon if you F12 on `Enum` (not `enum`) in VS2019, it takes you to metadata which includes `public abstract class Enum : ValueType, IComparable, ...` - so it looks like a class to me, since I think enum and Enum are synonyms. – StayOnTarget Nov 17 '20 at 22:07
  • @FreeText It is possible to add an extension method for an enum that is inside a class. Just that the extension method having to be in a top level static rather than being able to be scoped with (or at least near) the enum kind of stinks. – Paul Childs Jun 14 '22 at 02:38
  • @wingerse well, not as C# construct, but the underlying IL is pretty much the same between an enum and a static class with constant fields named like the enum values. In the context of this question this does not help, but thought it might be an interesting fun fact. – Ardor Jul 19 '22 at 13:04
90

You can also add an extension method to the Enum type rather than an instance of the Enum:

/// <summary> Enum Extension Methods </summary>
/// <typeparam name="T"> type of Enum </typeparam>
public class Enum<T> where T : struct, IConvertible
{
    public static int Count
    {
        get
        {
            if (!typeof(T).IsEnum)
                throw new ArgumentException("T must be an enumerated type");

            return Enum.GetNames(typeof(T)).Length;
        }
    }
}

You can invoke the extension method above by doing:

var result = Enum<Duration>.Count;

It's not a true extension method. It only works because Enum<> is a different type than System.Enum.

ShawnFeatherly
  • 2,470
  • 27
  • 20
  • 1
    Can the class be `static` to ensure all its methods behave like extensions? – Jatin Sanghvi Feb 04 '18 at 01:40
  • 27
    For future readers: the name ambiguity of `Enum` is a bit confusing. The class could also be called `EnumUtils` and the method call would resolve to `EnumUtils.Count`. – Namoshek Feb 27 '19 at 08:02
  • 9
    As of C# 7.3 instead of `where T : struct, IConvertible` you can actually use `where T : System.Enum` (and then also remove the ArgumentException, I guess) – Tobias Xy Oct 19 '20 at 13:06
65

Of course you can, say for example, you want to use the DescriptionAttribue on your enum values:

using System.ComponentModel;

public enum Duration 
{ 
    [Description("Eight hours")]
    Day,

    [Description("Five days")]
    Week,

    [Description("Twenty-one days")] 
    Month 
}

Now you want to be able to do something like:

Duration duration = Duration.Week;
var description = duration.GetDescription(); // will return "Five days"

Your extension method GetDescription() can be written as follows:

using System.ComponentModel;
using System.Reflection;

public static string GetDescription(this Enum value)
{
    FieldInfo fieldInfo = value.GetType().GetField(value.ToString());
    if (fieldInfo == null) return null;
    var attribute = (DescriptionAttribute)fieldInfo.GetCustomAttribute(typeof(DescriptionAttribute));
    return attribute.Description;
}
malat
  • 12,152
  • 13
  • 89
  • 158
Stacked
  • 6,892
  • 7
  • 57
  • 73
  • i was looking to create a extension to almost exactly what you sample did, except my use DisplayAttribute Localized GetDescription. cheers – George Dec 29 '17 at 13:41
  • This is a nice alternative, though I think the namespace is just System.ComponentModel? – TomDestry Dec 29 '18 at 16:39
  • 1
    Nice perspective and thank you for showing the implementation as well as the extension code. To pile on: with your implementation, you can also call it like this: var description = Duration.Week.GetDescription(); – Spencer Sullivan Jun 01 '20 at 16:01
  • OK, the method GetDescription() that you wrote would work for some other enum too, but I wonder can it be simplified if you declare it with (this Duration value) instead of (this Enum value) and then you know that you work on Duration type specificaly? – ivo.tisljar Sep 03 '22 at 05:41
47

All answers are great, but they are talking about adding extension method to a specific type of enum.

What if you want to add a method to all enums like returning an int of current value instead of explicit casting?

public static class EnumExtensions
{
    public static int ToInt<T>(this T soure) where T : IConvertible//enum
    {
        if (!typeof(T).IsEnum)
            throw new ArgumentException("T must be an enumerated type");

        return (int) (IConvertible) soure;
    }

    //ShawnFeatherly funtion (above answer) but as extention method
    public static int Count<T>(this T soure) where T : IConvertible//enum
    {
        if (!typeof(T).IsEnum)
            throw new ArgumentException("T must be an enumerated type");

        return Enum.GetNames(typeof(T)).Length;
    }
}

The trick behind IConvertible is its Inheritance Hierarchy see MDSN

Thanks to ShawnFeatherly for his answer

Palle Due
  • 5,929
  • 4
  • 17
  • 32
Basheer AL-MOMANI
  • 14,473
  • 9
  • 96
  • 92
10

A Simple workaround.

public static class EnumExtensions
{
    public static int ToInt(this Enum payLoad) {

        return ( int ) ( IConvertible ) payLoad;

    }
}

int num = YourEnum.AItem.ToInt();
Console.WriteLine("num : ", num);
M. Hamza Rajput
  • 7,810
  • 2
  • 41
  • 36
8

You can create an extension for anything, even object(although that's not considered best-practice). Understand an extension method just as a public static method. You can use whatever parameter-type you like on methods.

public static class DurationExtensions
{
  public static int CalculateDistanceBetween(this Duration first, Duration last)
  {
    //Do something here
  }
}
Community
  • 1
  • 1
Tim Schmelter
  • 450,073
  • 74
  • 686
  • 939
6

See MSDN.

public static class Extensions
{
  public static string SomeMethod(this Duration enumValue)
  {
    //Do something here
    return enumValue.ToString("D"); 
  }
}
TPAKTOPA
  • 2,462
  • 1
  • 19
  • 26
LukeHennerley
  • 6,344
  • 1
  • 32
  • 50
  • 7
    A `void` return value on an enum is kind of weird. I'd think about a more realistic sample. – psubsee2003 Mar 13 '13 at 14:41
  • 4
    @psubsee2003 the OP surely has enough knowledge to change this to suit his needs? Why does the sample matter, it's enough to answer the initial question. – LukeHennerley Mar 13 '13 at 14:46
  • 3
    Am I the only one who finds the code examples on MSDN weird? Most of the time you need some real effort to understand what they're trying to do! – Stacked Sep 23 '16 at 07:26
1

we have just made an enum extension for c# https://github.com/simonmau/enum_ext

It's just a implementation for the typesafeenum, but it works great so we made a package to share - have fun with it

public sealed class Weekday : TypeSafeNameEnum<Weekday, int>
{
    public static readonly Weekday Monday = new Weekday(1, "--Monday--");
    public static readonly Weekday Tuesday = new Weekday(2, "--Tuesday--");
    public static readonly Weekday Wednesday = new Weekday(3, "--Wednesday--");
    ....

    private Weekday(int id, string name) : base(id, name)
    {
    }

    public string AppendName(string input)
    {
        return $"{Name} {input}";
    }
}

I know the example is kind of useless, but you get the idea ;)

simonmau
  • 69
  • 1
  • 3