2009-03-25 17 views
21

Meine Frage wird am besten mit einem Beispiel veranschaulicht.Zusätzliche Informationen mit .NET Enum verknüpfen

Angenommen, ich habe die ENUM:

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

Ich mag jede Richtung den Einheitsvektor zuzuordnen diese Richtung entspricht. Zum Beispiel möchte ich etwas, das für North, (-1, 0) für West, etc. zurückgibt. Ich weiß, dass Sie in Java eine Methode innerhalb der Enumeration deklarieren könnten, die diese Funktionalität bereitstellen könnte.

Meine aktuelle Lösung ist eine statische Methode - innerhalb der Klasse, die die Enum definiert - die einen Vektor zurückgibt, der der in ArrowDirection übergebenen entspricht (die Methode verwendet eine HashTable, um die Suche durchzuführen, aber das ist nicht wirklich wichtig) . Das scheint ... unrein.

Frage:
Gibt es eine Best-Practice-Lösung zum Speichern zusätzlicher Informationen, die einer Enum in .NET entsprechen?

Antwort

37

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! So, 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; 
     } 
    } 
} 

Jetzt können Sie dies tun:

var unitVector = ArrowDirection.North.UnitVector(); 

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

Here's another example on my blog.

+0

Das ist ziemlich cool. Obwohl ich über Erweiterungen wusste, habe ich nie gedacht, sie für Enum-Erweiterung zu verwenden –

+0

Ja, ich entweder zuerst. Ein Freund hat mir davon erzählt. Es ist sehr schön. Ich war auch überrascht zu erfahren (kürzlich, hier auf SO), dass Sie eine Erweiterungsmethode für einen Nullwert aufrufen können. Es funktioniert immer noch, weil es eine statische Methode ist. Wie üblich hat das C# -Team großartige Arbeit geleistet, indem es diese Funktionen durchdacht hat. –

+0

Sie erhalten die akzeptierte Antwort. Ich habe es versucht und es funktioniert perfekt. Das einzige ist. Wo genau sollte ich das Enum deklarieren? Wenn ich es in der Klasse lasse, heißt es, dass es weniger zugänglich ist. Ich musste eine "ClassName_Enums" -Klasse erstellen, damit es funktioniert ... – colithium

3

Ich habe darüber gebloggt here.

Versuchen Sie etwas wie das mit Attributes.

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

    } 

    } 

Statt Beschreibung, nutzen Sie Ihre individuelle Immobilie

0

Eine Sache, die Sie bei der „typsichere Enum“ Muster aussehen könnte. Auf diese Weise können Sie eine ENUM erstellen, die tatsächlich ein vollwertiges statisches Objekt ist, die Methoden können/Eigenschaften/etc ..

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 ich bevorzuge es gegenüber einfachen Enums. (Es ist sprachunabhängig - es funktioniert in Java, C# oder so ziemlich jeder OO-Sprache).

+0

ich es auch benutzt habe und wie es. Aber erst kürzlich habe ich etwas gefunden, das ich noch mehr mag. Sie können Erweiterungsmethoden auf enums anwenden! Lustig wie viel Freude das bringt ... aber es ist wirklich schön. –

+0

Ich muss das überprüfen, danke für die Info –

0

Ihre statische Methode Ansatz scheint mir ziemlich sauber. Sie kapseln sowohl die enum als auch die statische Methode innerhalb derselben Klasse ein. Änderungen an der Enumeration sind in dieser einzelnen Klasse zusammengefasst.

Das Hinzufügen einer Methode zur Enumeration (nach Java) scheint etwas komplizierter zu machen, was wirklich ein sehr einfaches Konzept ist.

Der attributbasierte Ansatz ist interessant, scheint aber im Vergleich zu einer statischen Methode noch einmal zu komplizieren.

1
using System.ComponentModel; 
using System.Reflection; 


public enum ArrowDirection 
{ 

[Description("Northwards")] 
North, 

[Description("Southwards")] 
South, 

[Description("Eastwards")] 
East, 

[Description("Westwards")] 
West 
} 

...

eine Erweiterungsmethode Erstellen Sie 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; 

    } 
} 
+0

Das sieht nicht wie eine Erweiterungsmethode aus. Wo ist der 'this'-Parameter? Woher kommt 'ToDescription'? Soll das die Erweiterungsmethode sein? – CoderDennis

Verwandte Themen