web-dev-qa-db-fra.com

Comment ajouter des méthodes d'extension à Enums

J'ai ce code Enum:

enum Duration { Day, Week, Month };

Puis-je ajouter une méthode d'extension pour cet Enum?

95
user2110292

Selon ce site :

Les méthodes d'extension fournissent un moyen d'écrire des méthodes pour les classes existantes d'une manière que les autres membres de votre équipe pourraient réellement découvrir et utiliser. Étant donné que les énumérations sont des classes comme les autres, il n’est pas surprenant que vous puissiez les étendre, comme par exemple:

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

Je pense que les enums ne sont pas le meilleur choix en général, mais au moins, cela vous permet de centraliser une partie du commutateur/si vous les manipulez et de les abstraire un peu jusqu'à ce que vous puissiez faire quelque chose de mieux. N'oubliez pas de vérifier que les valeurs sont également dans la plage.

Vous pouvez en lire plus ici à Microsft MSDN.

90
One Man Crew

Vous pouvez également ajouter une méthode d’extension au type Enum plutôt qu’une instance de 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;
        }
    }
}

Vous pouvez appeler la méthode d'extension ci-dessus en effectuant:

var result = Enum<Duration>.Count;

Ce n'est pas une vraie méthode d'extension. Cela ne fonctionne que parce que Enum <> est d'un type différent de System.Enum.

38
ShawnFeatherly

Bien sûr, vous pouvez, par exemple, utiliser les valeurs DescriptionAttribue sur vos valeurs enum:

using System.ComponentModel.DataAnnotations;

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

    [Description("Five days")]
    Week,

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

Maintenant, vous voulez pouvoir faire quelque chose comme:

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

Votre méthode d'extension GetDescription() peut être écrite comme suit:

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;
}
32
Stacked

Toutes les réponses sont bonnes, mais il est question d’ajouter une méthode d’extension à un type d’énum spécifique.

Que faire si vous souhaitez ajouter une méthode à toutes les énumérations, telle que le renvoi d'un int de valeur actuelle au lieu d'une conversion explicite?

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

L'astuce derrière IConvertible est sa hiérarchie d'héritage, voir MDSN

Merci à ShawnFeatherly pour sa réponse

24

Vous pouvez créer une extension pour n'importe quoi, même object (bien que ce soit pas considéré comme une pratique exemplaire ). Comprendre une méthode d’extension comme un public static méthode. Vous pouvez utiliser le type de paramètre de votre choix pour les méthodes.

public static class DurationExtensions
{
  public static int CalculateDistanceBetween(this Duration first, Duration last)
  {
    //Do something here
  }
}
7
Tim Schmelter

Voir MSDN .

public static class Extensions
{
  public static string SomeMethod(this Duration enumValue)
  {
    //Do something here
    return enumValue.ToString("D"); 
  }
}
5
LukeHennerley

nous venons de créer une extension enum pour c # https://github.com/simonmau/enum_ext

C'est juste une implémentation pour le typeafeenum, mais cela fonctionne très bien, nous avons donc créé un paquet à partager - amusez-vous avec elle

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

Je sais que l'exemple est un peu inutile, mais vous voyez l'idée;)

1
simonmau