web-dev-qa-db-de.com

So fügen Sie Enums Erweiterungsmethoden hinzu

Ich habe diesen Enum-Code:

enum Duration { Day, Week, Month };

Kann ich eine Erweiterungsmethode für diese Aufzählung hinzufügen?

95
user2110292

Demnach site :

Erweiterungsmethoden bieten eine Möglichkeit, Methoden für vorhandene Klassen so zu schreiben, wie andere Personen in Ihrem Team sie möglicherweise tatsächlich erkennen und verwenden. Angesichts der Tatsache, dass Aufzählungen Klassen wie jede andere sind, sollte es nicht überraschen, dass Sie sie erweitern können, wie zum Beispiel:

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

Ich denke, Aufzählungen sind im Allgemeinen nicht die beste Wahl, aber zumindest können Sie so einen Teil des Switches zentralisieren/wenn Sie damit umgehen und sie ein wenig abstrahieren, bis Sie etwas Besseres tun können. Denken Sie daran, zu überprüfen, ob die Werte auch im Bereich liegen.

Sie können mehr lesen hier bei Microsoft MSDN.

90
One Man Crew

Sie können dem Enum-Typ auch eine Erweiterungsmethode hinzufügen, anstatt eine Instanz von 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;
        }
    }
}

Sie können die obige Erweiterungsmethode folgendermaßen aufrufen:

var result = Enum<Duration>.Count;

Es ist keine echte Erweiterungsmethode. Dies funktioniert nur, weil Enum <> ein anderer Typ als System.Enum ist.

38
ShawnFeatherly

Natürlich können Sie zum Beispiel sagen, dass Sie DescriptionAttribue für Ihre enum -Werte verwenden möchten:

using System.ComponentModel.DataAnnotations;

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

    [Description("Five days")]
    Week,

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

Jetzt möchten Sie in der Lage sein, Folgendes zu tun:

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

Ihre Erweiterungsmethode GetDescription() kann wie folgt geschrieben werden:

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

Alle Antworten sind großartig, aber es geht darum, einer bestimmten Art von Aufzählung eine Erweiterungsmethode hinzuzufügen.

Was ist, wenn Sie eine Methode zu allen Aufzählungen hinzufügen möchten, z. B. ein int des aktuellen Werts anstelle eines expliziten Castings zurückgeben möchten?

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

Der Trick hinter IConvertible ist seine Vererbungshierarchie, siehe MDSN

Vielen Dank an ShawnFeatherly für seine Antwort

24

Sie können für alles eine Erweiterung erstellen, auch für object (obwohl dies nicht als bewährte Methode gilt ). Verstehen Sie eine Erweiterungsmethode nur als public static Methode. Sie können für Methoden jeden gewünschten Parametertyp verwenden.

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

Siehe MSDN .

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

wir haben gerade eine Enum-Erweiterung für c # https://github.com/simonmau/enum_ext erstellt

Es ist nur eine Implementierung für das typesafeenum, aber es funktioniert großartig, also haben wir ein Paket zum Teilen zusammengestellt - viel Spaß damit

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

Ich weiß, das Beispiel ist irgendwie nutzlos, aber Sie haben die Idee;)

1
simonmau