2008-09-15 17 views
1

Gibt es eine gute Lösung, um eine parametrierte Enum in C# 3.0 darzustellen? Ich bin auf der Suche nach etwas wie OCaml oder Haxe hat. Ich denke nur an Klassenhierarchie mit einem einfachen Enum-Feld für den einfachen Wechsel, vielleicht gibt es bessere Ideen?Der beste Weg, um eine parametrisierte Enum in C# darzustellen?

Siehe Ocaml Beispiel unten in eine der Antworten, ein Haxe Code folgt:

enum Tree { 
    Node(left: Tree, right: Tree); 
    Leaf(val: Int); 
} 
+0

Für diejenigen von uns, die OCaml oder haXe nicht kennen, könnten Sie und Beispiel bereitstellen? –

Antwort

7

Nicht vertraut mit OCaml oder Haxe, und nicht klug genug, um die anderen Erklärungen zu verstehen, ging ich und schaute die Haxe enum documentation - die 'Enum Type Parameters' Bit am unteren Rand scheint der relevante Teil zu sein.

Mein Verständnis auf dieser Grundlage lautet wie folgt:

A ‚normale‘ Enum im Grunde ein Wert ist, der auf die Dinge beschränkt, die Sie in Ihrer Enumerationsdefinition definiert haben. C# Beispiel:

enum Color{ Red, Green, Yellow, Blue }; 
Color c = Color.Red; 

c kann entweder Red, Green, Yellow oder Blue, aber sonst nichts.

In Haxe, komplexe Typen Aufzählungen, konstruiertes Beispiel von ihrer Seite hinzufügen:

enum Cell<T>{ 
    empty; 
    cons(item : T, next : Cell<T>) 
} 

Cell<int> c = <I don't know>; 

Was soll bedeuten scheint, dass c auf das beschränkt ist entweder die wörtliche Wert empty sein (wie unser altmodische C# enums), oder es kann auch ein komplexer Typ cons(item, next) sein, wobei ein T und next ein Cell<T> ist.

Nicht immer diese verwendet haben es sieht aus wie es ist wahrscheinlich einige anonyme Typen zu erzeugen (wie, wie der C# Compiler tut, wenn Sie new { Name='Joe'} tun.
Jedes Mal, wenn Sie ‚Zugang‘ der ENUM-Wert, haben Sie item und next zu erklären, wenn Sie tun so, und es sieht aus wie sie auf temporäre lokale Variablen gebunden bekommen

Haxe Beispiel - Sie können sehen, ‚next‘ als temporäre lokale Variable verwendet wird, um Daten aus der anonymen Nachteile Struktur zu ziehen.

switch(c) { 
    case empty : 0; 
    case cons(item,next): 1 + cell_length(next); 
} 

Um ehrlich zu sein, das hat mich umgehauen, als ich auf das klickte, was es zu tun schien. Es scheint unglaublich mächtig zu sein, und ich sehe, warum Sie nach einer ähnlichen Funktion in C# suchen.

C# -Enums sind ziemlich genau die gleichen wie C/++ - Enums, von denen sie ursprünglich kopiert wurden.Es ist im Grunde eine nette Art, #define Red 1 zu sagen, so dass der Compiler Vergleiche und Speicher mit Ganzzahlen anstelle von Strings durchführen kann, wenn Sie Objekte übergeben.

Mein Stich in C# wäre, Generika und Schnittstellen zu verwenden. Etwas wie folgt aus:

public interface ICell<T> { 
    T Item{ get; set; } 
    ICell<T>{ get; set; } 
} 

class Cons<T> : ICell<T> { 
    public T Item{ get; set; } /* C#3 auto-backed property */ 
    public Cell<T> Next{ get; set; } 
} 

class EmptyCell<T> : ICell<T>{ 
    public T Item{ get{ return default(T); set{ /* do nothing */ }; } 
    public ICell<T> Next{ get{ return null }; set{ /* do nothing */; } 
} 

Dann könnten Sie ein List<ICell<T>> haben, welche Elemente und nächste Zelle enthalten würde, und man konnte EmptyCell am Ende ein (oder einfach nur die Next ausdrücklich auf null gesetzt). Die Vorteile wären, dass EmptyCell keine Elementvariablen enthält, würde es keinen Speicherplatz (wie die empty in Haxe) benötigen, während eine Zelle Cons würde.
Der Compiler kann auch die Methoden in EmptyCell inline/optimieren, da sie nichts tun, so dass es eine Geschwindigkeitszunahme über nur Cons mit seiner Mitgliedsdatenmenge auf null geben kann.

Ich weiß es nicht wirklich. Ich würde andere mögliche Lösungen begrüßen, da ich nicht besonders stolz auf meine bin :-)

+0

Danke, daran habe ich eigentlich gedacht, aber du hast eine sehr detaillierte Erklärung gegeben, wie es gemacht werden könnte! Und ja wahrscheinlich nichts besseres ... –

0

C# (.NET Framework im Allgemeinen, soweit ich weiß) nicht unterstützt parametrisierte Aufzählungen wie Java tut . Davon abgesehen, sollten Sie sich Attribute anschauen. Einige der Funktionen, zu denen Java-Enumerationen in der Lage sind, sind durch Attribute einigermaßen machbar.

+0

Nun korrigieren Sie mich, wenn ich falsch liege, aber ich denke Java-Enums erlauben Parameter - aber das gleiche für alle Enum-Konstrukte, nicht eine eindeutige Parameterliste pro Konstrukt wie OCaml. Ich brauche den Ocaml-Weg, Attribute helfen hier nicht viel - aber trotzdem danke! –

0

Was ist falsch daran, nur eine Klasse dafür zu verwenden? Es ist hässlich, aber so haben die Java-Leute es gemacht, bis sie Enum-Unterstützung in Sprache integriert hatten!

+0

Das Problem mit Klassen ist, dass es schwierig ist, sie dann zu wechseln. Angesichts eines Enum-Wertes möchte ich schnell und einfach verstehen, was es ist und welche Argumente es gibt. Ich kann das mit einer Klassenhierarchie und einem einfachen Enum-Schalter, aber das klingt nicht zu elegant. –

1

Verwenden Sie eine Klasse, die mit statischen Eigenschaften die Aufzählungswerte darstellen. Sie können optional einen privaten Konstruktor verwenden, um alle Verweise auf die Klasse durch eine statische Eigenschaft zu erzwingen.

Werfen Sie einen Blick auf die Klasse System.Drawing.Color. Es verwendet diesen Ansatz.

Verwandte Themen