23 Stimmen

Zusätzliche Informationen mit .NET Enum verknüpfen

Meine Frage lässt sich am besten anhand eines Beispiels veranschaulichen.

Angenommen, ich habe die Aufzählung:

public enum ArrowDirection
{
    North,
    South,
    East,
    West
}

Ich möchte den Einheitsvektor, der jeder Richtung entspricht, mit dieser Richtung verknüpfen. Ich möchte zum Beispiel etwas, das (0, 1) für Norden, (-1, 0) für Westen usw. zurückgibt. Ich weiß, dass man in Java eine Methode innerhalb der Aufzählung deklarieren kann, die diese Funktionalität bietet.

Meine aktuelle Lösung ist eine statische Methode - innerhalb der Klasse, die die Enum definiert -, die einen Vektor entsprechend der übergebenen in ArrowDirection (die Methode verwendet eine HashTable, um die Suche zu erreichen, aber das ist nicht wirklich wichtig) zurückgibt. Dies scheint... unsauber zu sein.

Frage:
Gibt es eine Best-Practice-Lösung für die Speicherung zusätzlicher Informationen, die einem Enum in .NET entsprechen?

41voto

Charlie Flowers Punkte 17000

Es gibt eine FANTASTISCHE neue Möglichkeit, dies in C# 3.0 zu tun. Der Schlüssel ist diese schöne Tatsache: Enums können Erweiterungsmethoden haben! Also, hier ist, was Sie tun können:

public enum ArrowDirection
{
    North,
    South,
    East,
    West
}

public static class ArrowDirectionExtensions
{
     public static UnitVector UnitVector(this ArrowDirection self)
     {
         // Replace this with a dictionary or whatever you want ... you get the idea
         switch(self)
         {
             case ArrowDirection.North:
                 return new UnitVector(0, 1);
             case ArrowDirection.South:
                 return new UnitVector(0, -1);
             case ArrowDirection.East:
                 return new UnitVector(1, 0);
             case ArrowDirection.West:
                 return new UnitVector(-1, 0);
             default:
                 return null;
         }
     }
}

Das können Sie jetzt tun:

var unitVector = ArrowDirection.North.UnitVector();

Toll! Ich habe das erst vor etwa einem Monat herausgefunden, aber es ist eine sehr schöne Folge der neuen C# 3.0-Funktionen.

Hier ist ein weiteres Beispiel in meinem Blog.

3voto

Cherian Punkte 18451

Ich habe darüber gebloggt aquí .

Probieren Sie etwas Ähnliches aus mit Attribute .

  public enum Status {

    [Status(Description = "Not Available")]      

    Not_Available = 1,      

    [Status(Description = "Available For Game")] 

    Available_For_Game = 2,      

    [Status(Description = "Available For Discussion")] 

    Available_For_Discussion = 3,

  }

  public class StatusEnumInfo {

    private static StatusAttribute[] edesc; 

    public static String GetDescription(object e)

    {

      System.Reflection.FieldInfo f = e.GetType().GetField(e.ToString()); 

      StatusEnumInfo.edesc = f.GetCustomAttributes(typeof(StatusAttribute), false) as StatusAttribute[]; 

      if (StatusEnumInfo.edesc != null && StatusEnumInfo.edesc.Length == 1)         

        return StatusEnumInfo.edesc[0].Description; 

      else         

        return String.Empty;

    } 

    public static object GetEnumFromDesc(Type t, string desc)

    {

      Array x = Enum.GetValues(t); 

      foreach (object o in x) {

        if (GetDescription(o).Equals(desc)) {

          return o;

        }

      } return String.Empty;

    }

  }

  public class StatusAttribute : Attribute {

    public String Description { get; set; }

  }

  public class Implemenation {

    public void Run()

    {

      Status statusEnum = (Status)StatusEnumInfo.GetEnumFromDesc(typeof(Status), "Not Available"); 

      String statusString = StatusEnumInfo.GetDescription(Status.Available_For_Discussion);

    }

  }

Anstelle von Beschreibung , verwenden Sie Ihre benutzerdefinierte Eigenschaft

1voto

Mitch Wheat Punkte 287474
using System.ComponentModel;
using System.Reflection;

public enum ArrowDirection
{

[Description("Northwards")]
North,

[Description("Southwards")]
South,

[Description("Eastwards")]
East,

[Description("Westwards")]
West
}

...

Erstellen Sie eine Erweiterungsmethode, um eine Liste von Beschreibungen zu erhalten:

public static class Enum<T> where T : struct
{

    /// <summary>
    /// Gets a collection of the enum value descriptions.
    /// </summary>
    /// <returns></returns>
    public static IList<string> GetDescriptions()
    {
        List<string> descriptions = new List<string>();
        foreach (object enumValue in Enum<T>.GetValues())
        {
            descriptions.Add(((Enum)enumValue).ToDescription());
        }
        return descriptions;

    }
}

0voto

Andy White Punkte 83877

Eine Möglichkeit, die Sie sich ansehen könnten, ist das Muster "Type-Safe Enum". Damit können Sie eine Enum erstellen, die eigentlich ein vollwertiges statisches Objekt ist, das Methoden/Eigenschaften usw. haben kann.

http://www.javacamp.org/designPattern/enum.html

Joshua Bloch spricht über dieses Muster in seinem Buch "Effective Java". Ich habe es in vielen verschiedenen Situationen verwendet und bevorzuge es eigentlich gegenüber einfachen Enums. (Es ist sprachunabhängig - es funktioniert in Java, C# oder so ziemlich jeder OO-Sprache).

0voto

Ash Punkte 58914

Ihr Ansatz der statischen Methode scheint mir recht sauber zu sein. Sie kapseln sowohl das Enum als auch die statische Methode in derselben Klasse. Änderungen an der Enum werden in dieser einen Klasse zentralisiert.

Das Hinzufügen einer Methode zur Aufzählung (wie in Java) scheint die Komplexität von etwas zu erhöhen, das eigentlich ein sehr einfaches Konzept ist.

Der attributbasierte Ansatz ist interessant, scheint aber im Vergleich zu einer statischen Methode wieder einmal zu kompliziert zu sein.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X