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 :-)
Für diejenigen von uns, die OCaml oder haXe nicht kennen, könnten Sie und Beispiel bereitstellen? –