Ist es möglich, eine implizite Konvertierung von Aufzählungen in c # zu definieren?
etwas, das dies erreichen könnte?
public enum MyEnum
{
one = 1, two = 2
}
MyEnum number = MyEnum.one;
long i = number;
Wenn nicht, warum nicht?
c#
enums
implicit-conversion
implicit
Adam Naylor
quelle
quelle
enum YesNo {Yes, No}
, die implizit in bool konvertiert werden könnte.Antworten:
Es gibt eine Lösung. Folgendes berücksichtigen:
Das Obige bietet implizite Konvertierung:
Dies ist ein gutes Stück mehr Arbeit als das Deklarieren einer normalen Aufzählung (obwohl Sie einige der oben genannten in eine gemeinsame generische Basisklasse umgestalten können). Sie können noch weiter gehen, indem Sie die Basisklasse IComparable & IEquatable implementieren lassen und Methoden hinzufügen, um den Wert von DescriptionAttributes, deklarierten Namen usw. zurückzugeben.
Ich habe eine Basisklasse (RichEnum <>) geschrieben, um die meisten Grunzarbeiten zu erledigen, wodurch die obige Aufzählung der Aufzählungen auf Folgendes reduziert wird:
Die Basisklasse (RichEnum) ist unten aufgeführt.
quelle
Sie können keine impliziten Konvertierungen durchführen (außer Null), und Sie können keine eigenen Instanzmethoden schreiben. Sie können jedoch wahrscheinlich Ihre eigenen Erweiterungsmethoden schreiben:
Dies gibt Ihnen jedoch nicht viel (im Vergleich zu einer expliziten Besetzung).
Eine der Hauptzeiten, in denen ich gesehen habe, dass Leute dies wollen, ist die
[Flags]
Manipulation über Generika - dh einebool IsFlagSet<T>(T value, T flag);
Methode. Leider unterstützt C # 3.0 keine Operatoren für Generika, aber Sie können dies mit solchen Dingen umgehen , die Operatoren mit Generika vollständig verfügbar machen.quelle
quelle
static class
nehme ich an. Es gibt keinen Vorteil, für beide Fälle im endgültigenIL
Code zu argumentieren .Ich habe Marks ausgezeichnete generische RichEnum-Basisklasse angepasst.
Festsetzung
Ein großes Lob an Mark für die großartige Idee + Implementierung, hier ist für euch alle:
Ein Anwendungsbeispiel, das ich auf Mono ausgeführt habe:
Ausgabe produzieren
Hinweis: Für Mono 2.6.7 ist eine zusätzliche explizite Besetzung erforderlich, die bei Verwendung von Mono 2.8.2 nicht erforderlich ist ...
quelle
FirstOrDefault
, um zu vermeiden, dass es nur ein einziges Attribut gibt). Ob solche Dinge „eine gute Idee“ sind oder nicht (oder eine schlechte ), hängt natürlich vom Kontext abTDerived instance = (TDerived)field.GetValue(null);
dazu,instance
dass es so istnull
. Es scheint, dass die Mono-Laufzeit eine andere Reihenfolge der Typinitialisierung haben muss als die .NET-Laufzeit, die dies ermöglicht. Rätselhaft! Ich musste diesen Code stattdessen in eine statische Methode verschieben und ihn vom Typinitialisierer in der Unterklasse aufrufen.Sie können keine impliziten Konvertierungen für Aufzählungstypen deklarieren, da diese keine Methoden definieren können. Das implizite Schlüsselwort C # wird in eine Methode kompiliert, die mit 'op_' beginnt, und in diesem Fall würde es nicht funktionieren.
quelle
Sie könnten wahrscheinlich, aber nicht für die Aufzählung (Sie können keine Methode hinzufügen). Sie können Ihrer eigenen Klasse eine implizite Konvertierung hinzufügen, damit eine Aufzählung in diese konvertiert werden kann.
Die Frage wäre warum?
Im Allgemeinen vermeidet .Net implizite Konvertierungen (und Sie sollten dies auch tun), bei denen Daten verloren gehen können.
quelle
Wenn Sie die Basis der Aufzählung als lang definieren, können Sie eine explizite Konvertierung durchführen. Ich weiß nicht, ob Sie implizite Konvertierungen verwenden können, da für Enums keine Methoden definiert sind.
Beachten Sie auch, dass eine nicht initialisierte Aufzählung standardmäßig den Wert 0 oder das erste Element verwendet. In der obigen Situation ist es daher wahrscheinlich am besten, diese ebenfalls zu definieren
zero = 0
.quelle
: long
hier nicht; Die explizite Konvertierung würde ohne sie gut funktionieren. Die einzige rechtliche implizite Konvertierung ist Null.Aufzählungen sind aus diesem Grund für mich weitgehend nutzlos, OP.
Am Ende mache ich die ganze Zeit Fotos:
die einfache Lösung
Ein klassisches Beispielproblem ist das VirtualKey-Set zum Erkennen von Tastendrücken.
Das Problem hierbei ist, dass Sie das Array nicht mit der Aufzählung indizieren können, da es die Aufzählung nicht implizit in ushort konvertieren kann (obwohl wir die Aufzählung sogar auf ushort basieren).
In diesem speziellen Kontext werden Aufzählungen durch die folgende Datenstruktur überholt. . . .
quelle
Ich habe ein Problem mit der Antwort von sehe umgangen, als ich den Code auf MS .net (nicht Mono) ausführte . Für mich ist das Problem speziell auf .net 4.5.1 aufgetreten, aber auch andere Versionen scheinen betroffen zu sein.
Das Thema
ein Zugriff
public static TDervied MyEnumValue
durch Reflexion (überFieldInfo.GetValue(null)
nicht nicht initialize genannte Feld.Die Problemumgehung
Anstatt
TDerived
Instanzen beim statischen Initialisierer NamenRichEnum<TValue, TDerived>
zuzuweisen, erfolgt dies beim ersten Zugriff auf trägeTDerived.Name
. Der Code:was - in meinem Fall - basiert auf
EquatableBase<T>
:Hinweis
Der obige Code enthält nicht alle Funktionen von Marks ursprünglicher Antwort!
Vielen Dank
Vielen Dank an Mark für die Bereitstellung seiner
RichEnum
Implementierung und an sehe für die Bereitstellung einiger Verbesserungen!quelle
Ich habe von hier aus eine noch einfachere Lösung gefunden: /codereview/7566/enum-vs-int-wrapper-struct Ich habe den folgenden Code über diesen Link eingefügt, nur für den Fall, dass er in Zukunft nicht funktioniert.
quelle
Ich habe dieses Dienstprogramm erstellt, um eine Aufzählung in PrimitiveEnum und PrimitiveEnum in zu konvertieren
byte, sbyte, short, ushort, int, uint, long, or ulong
.Dies konvertiert also technisch jede Aufzählung in einen ihrer primitiven Werte.
Siehe Commit unter https://github.com/McKabue/McKabue.Extentions.Utility/blob/master/src/McKabue.Extentions.Utility/Enums/PrimitiveEnum.cs
quelle
uint
s gekennzeichnet sind, für die das Spiel selbst normalerweiseenum
s macht , aber das Framework weiß nichts darüber. Es(uint)
war ein Schmerz , wenn man das Framework aufrief. Ihre Idee rückwärts funktioniert perfekt. Anstatt das zustruct
speichernEnum
, habe ich ein, dasstruct IdNumber
das speichert,uint
aber implizit von demEnum
s konvertiert, das das Spiel verwendet. Anstatt die Parameter des Frameworks als einzugebenuint
, kann ich sie eingebenIdNumber
, und das Framework kann sie intern effizient weitergeben und sogar integrale Operationen an ihnen durchführen.Das Einführen impliziter Konvertierungen für Aufzählungstypen würde die Typensicherheit beeinträchtigen, daher würde ich dies nicht empfehlen. Warum willst du das tun? Der einzige Anwendungsfall, den ich gesehen habe, ist, wenn Sie die Aufzählungswerte in eine Struktur mit einem vordefinierten Layout einfügen möchten. Aber selbst dann können Sie den Aufzählungstyp in der Struktur verwenden und dem Marshaller einfach sagen, was er damit machen soll.
quelle