Ich habe die folgende Aufzählung:
public enum AuthenticationMethod
{
FORMS = 1,
WINDOWSAUTHENTICATION = 2,
SINGLESIGNON = 3
}
Das Problem ist jedoch, dass ich das Wort "FORMS" benötige, wenn ich nach AuthenticationMethod.FORMS und nicht nach der ID 1 frage.
Ich habe die folgende Lösung für dieses Problem gefunden ( Link ):
Zuerst muss ich ein benutzerdefiniertes Attribut namens "StringValue" erstellen:
public class StringValue : System.Attribute
{
private readonly string _value;
public StringValue(string value)
{
_value = value;
}
public string Value
{
get { return _value; }
}
}
Dann kann ich dieses Attribut meinem Enumerator hinzufügen:
public enum AuthenticationMethod
{
[StringValue("FORMS")]
FORMS = 1,
[StringValue("WINDOWS")]
WINDOWSAUTHENTICATION = 2,
[StringValue("SSO")]
SINGLESIGNON = 3
}
Und natürlich brauche ich etwas, um diesen StringValue abzurufen:
public static class StringEnum
{
public static string GetStringValue(Enum value)
{
string output = null;
Type type = value.GetType();
//Check first in our cached results...
//Look for our 'StringValueAttribute'
//in the field's custom attributes
FieldInfo fi = type.GetField(value.ToString());
StringValue[] attrs =
fi.GetCustomAttributes(typeof(StringValue),
false) as StringValue[];
if (attrs.Length > 0)
{
output = attrs[0].Value;
}
return output;
}
}
Gut, jetzt habe ich die Werkzeuge, um einen String-Wert für einen Enumerator zu erhalten. Ich kann es dann so verwenden:
string valueOfAuthenticationMethod = StringEnum.GetStringValue(AuthenticationMethod.FORMS);
Okay, jetzt funktionieren all diese Dinge wie ein Zauber, aber ich finde es eine Menge Arbeit. Ich habe mich gefragt, ob es dafür eine bessere Lösung gibt.
Ich habe auch etwas mit einem Wörterbuch und statischen Eigenschaften versucht, aber das war auch nicht besser.
this
vor derEnum
statischen Methode hinzufügen . Dann können Sie tunAuthenticationMethod.Forms.GetStringValue();
Antworten:
Versuchen Sie es mit einem Typ-Safe-Enum- Muster.
Aktualisieren Die explizite (oder implizite) Typkonvertierung kann von durchgeführt werden
Hinzufügen eines statischen Feldes mit Zuordnung
Füllen Sie diese Zuordnung im Instanzkonstruktor
und Hinzufügen eines benutzerdefinierten Typkonvertierungsoperators
quelle
Verwenden Sie die Methode
wie in (Angenommen, es
Shipper
handelt sich um eine definierte Aufzählung)Es gibt eine Reihe anderer statischer Methoden in der Enum-Klasse, die ebenfalls untersucht werden sollten ...
quelle
Sie können mit ToString () auf den Namen und nicht auf den Wert verweisen.
Die Dokumentation finden Sie hier:
http://msdn.microsoft.com/en-us/library/16c1xs4z.aspx
... und wenn Sie Ihre Aufzählungen in Pascal Case benennen (wie ich - wie ThisIsMyEnumValue = 1 usw.), können Sie das freundliche Formular mit einer sehr einfachen Regex drucken:
die leicht von jedem String aufgerufen werden kann:
Ausgänge:
Das erspart es, durch die Häuser zu laufen, benutzerdefinierte Attribute zu erstellen und diese an Ihre Aufzählungen anzuhängen oder Nachschlagetabellen zu verwenden, um einen Aufzählungswert mit einer benutzerfreundlichen Zeichenfolge zu verbinden. Das Beste ist, dass er sich selbst verwaltet und für jede Pascal Case-Zeichenfolge verwendet werden kann, die unendlich ist wiederverwendbarer. Natürlich erlaubt es dir nicht, einen anderen zu haben Anzeigenamen als Ihre Aufzählung haben, die Ihre Lösung bietet.
Ich mag Ihre ursprüngliche Lösung für komplexere Szenarien. Sie könnten Ihre Lösung noch einen Schritt weiter gehen und GetStringValue zu einer Erweiterungsmethode Ihrer Aufzählung machen, und dann müssten Sie nicht wie StringEnum.GetStringValue darauf verweisen ...
Sie können dann einfach direkt von Ihrer Enum-Instanz darauf zugreifen:
quelle
"(?!^)([^A-Z])([A-Z])", "$1 $2"
. SoHereIsATEST
wirdHere Is ATEST
.Leider ist die Reflexion, um Attribute für Aufzählungen zu erhalten, ziemlich langsam:
Siehe diese Frage: Kennt jemand einen schnellen Weg, um zu benutzerdefinierten Attributen für einen Aufzählungswert zu gelangen?
Das
.ToString()
ist auch bei Aufzählungen ziemlich langsam.Sie können jedoch Erweiterungsmethoden für Aufzählungen schreiben:
Dies ist nicht großartig, geht aber schnell und erfordert keine Reflexion für Attribute oder Feldnamen.
C # 6 Update
Wenn Sie C # 6 dann die neuen verwenden können
nameof
Bediener arbeiten für Aufzählungen, sonameof(MyEnum.WINDOWSAUTHENTICATION)
umgewandelt werden , um"WINDOWSAUTHENTICATION"
bei der Kompilierung , es ist der schnellste Weg zu machen Enum - Namen zu erhalten.Beachten Sie, dass dadurch die explizite Aufzählung in eine Inline-Konstante konvertiert wird, sodass dies für Aufzählungen in einer Variablen nicht funktioniert. Damit:
Aber...
quelle
Ich benutze eine Erweiterungsmethode:
Jetzt dekorieren Sie die
enum
mit:Wenn du anrufst
AuthenticationMethod.FORMS.ToDescription()
du wirst bekommen"FORMS"
.quelle
using System.ComponentModel;
Außerdem funktioniert diese Methode nur, wenn der String-Wert mit dem Namen der Aufzählung übereinstimmen soll. OP wollte einen anderen Wert.AuthenticationMethod.FORMS.ToDescription()
?Verwenden Sie einfach die
ToString()
MethodeUm auf die Zeichenfolge zu verweisen
Tomato
, verwenden Sie einfachquelle
.ToString()
Wert haben als den benutzerfreundlichen Wert, den Sie benötigen.any fruit = any.Tomato;
string tomato = fruit.ToString();
Sehr einfache Lösung hierfür mit .Net 4.0 und höher. Es wird kein anderer Code benötigt.
Um den String zu erhalten, verwenden Sie einfach:
oder
Der Wert ist "Aktiv" oder "Archiviert".
Informationen zu den verschiedenen Zeichenfolgenformaten (das "f" von oben) beim Aufrufen finden
Enum.ToString
Sie auf dieser Seite " Zeichenfolgen im Aufzählungsformat"quelle
Ich verwende das Description-Attribut aus dem System.ComponentModel-Namespace. Dekorieren Sie einfach die Aufzählung und rufen Sie sie mit diesem Code ab:
Als Beispiel:
Dieser Code eignet sich gut für Aufzählungen, bei denen Sie keinen "Anzeigenamen" benötigen, und gibt nur den .ToString () der Aufzählung zurück.
quelle
Ich mag die Antwort von Jakub Šturc sehr, aber es ist ein Nachteil, dass Sie sie nicht mit einer Switch-Case-Anweisung verwenden können. Hier ist eine leicht modifizierte Version seiner Antwort, die mit einer switch-Anweisung verwendet werden kann:
Sie erhalten also alle Vorteile der Antwort von Jakub Šturc, und wir können sie mit einer switch-Anweisung wie der folgenden verwenden:
quelle
public static int nextAvailable { get; private set; }
dann im Konstruktorthis.Value = nextAvailable++;
=
Bediener nicht einfach überlasten , damit der Schalter funktioniert? Ich habe dies in VB getan und kann es jetzt inselect case
Anweisung verwenden.Ich verwende eine Kombination aus mehreren der oben genannten Vorschläge, kombiniert mit etwas Caching. Jetzt kam mir die Idee von einem Code, den ich irgendwo im Internet gefunden habe, aber ich kann mich weder erinnern, woher ich ihn habe, noch finde ich ihn. Wenn also jemand etwas findet, das ähnlich aussieht, kommentieren Sie dies bitte mit der Zuschreibung.
Wie auch immer, die Verwendung betrifft die Typkonverter. Wenn Sie also an die Benutzeroberfläche binden, funktioniert dies einfach. Sie können das Jakub-Muster für eine schnelle Code-Suche erweitern, indem Sie vom Typkonverter in die statischen Methoden initialisieren.
Die Basisverwendung würde so aussehen
Der Code für den benutzerdefinierten Enum-Typ-Konverter lautet wie folgt:
}}
quelle
In Ihrer Frage haben Sie nie gesagt, dass Sie den numerischen Wert der Aufzählung tatsächlich irgendwo benötigen.
Wenn Sie keine Aufzählung vom Typ string benötigen (die kein integraler Typ ist und daher keine Basis für die Aufzählung sein kann), haben Sie folgende Möglichkeiten:
Sie können dieselbe Syntax wie enum verwenden, um darauf zu verweisen
Es ist etwas langsamer als bei numerischen Werten (Vergleichen von Zeichenfolgen anstelle von Zahlen), aber auf der positiven Seite wird keine Reflexion (langsam) verwendet, um auf die Zeichenfolge zuzugreifen.
quelle
Wie ich das als Erweiterungsmethode gelöst habe:
Aufzählung:
Verwendung (wobei o.OrderType eine Eigenschaft mit demselben Namen wie die Aufzählung ist):
Das gibt mir eine Zeichenfolge von "New Card" oder "Reload" anstelle des tatsächlichen Aufzählungswerts NewCard and Refill.
quelle
Aktualisieren: Besuch dieser Seite, 8 Jahre später, nachdem ich C # lange nicht berührt habe, scheint meine Antwort nicht mehr die beste Lösung zu sein. Ich mag die Konverterlösung, die mit Attributfunktionen verbunden ist, sehr.
Wenn Sie dies lesen, stellen Sie bitte sicher, dass Sie auch andere Antworten lesen.
(Hinweis: Sie sind über diesem)
Wie die meisten von Ihnen hat mir die ausgewählte Antwort von Jakub Šturc sehr gut gefallen , aber ich hasse es auch, Code zu kopieren und und zu versuchen, es so wenig wie möglich zu tun.
Deshalb habe ich mich für eine EnumBase-Klasse entschieden, von der der größte Teil der Funktionalität geerbt / integriert ist, sodass ich mich auf den Inhalt anstatt auf das Verhalten konzentrieren kann.
Das Hauptproblem bei diesem Ansatz basiert auf der Tatsache, dass Enum-Werte zwar typsichere Instanzen sind, die Interaktion jedoch mit der statischen Implementierung des Enum-Klassentyps erfolgt. Mit ein wenig Hilfe von Generika-Magie habe ich endlich die richtige Mischung gefunden. Hoffe, jemand findet das genauso nützlich wie ich.
Ich werde mit Jakubs Beispiel beginnen, aber Vererbung und Generika verwenden:
Und hier ist die Basisklasse:
quelle
Ich stimme Keith zu, kann aber (noch) nicht abstimmen.
Ich verwende eine statische Methode und eine swith-Anweisung, um genau das zurückzugeben, was ich will. In der Datenbank speichere ich tinyint und mein Code verwendet nur die tatsächliche Aufzählung, sodass die Zeichenfolgen den Anforderungen der Benutzeroberfläche entsprechen. Nach zahlreichen Tests ergab dies die beste Leistung und die größte Kontrolle über die Ausgabe.
Nach einigen Angaben führt dies jedoch zu einem möglichen Wartungsalptraum und einem gewissen Codegeruch. Ich versuche, ein Auge auf lange und viele Aufzählungen zu haben oder auf solche, die sich häufig ändern. Ansonsten war dies eine großartige Lösung für mich.
quelle
Wenn Sie hierher gekommen sind, um eine einfache "Aufzählung" zu implementieren, deren Werte jedoch Zeichenfolgen anstelle von Ints sind, ist hier die einfachste Lösung:
Implementierung:
quelle
static readonly
.Wenn ich mit diesem Problem konfrontiert werde, gibt es einige Fragen, auf die ich zuerst Antworten zu finden versuche:
Der einfachste Weg, dies zu tun, ist mit
Enum.GetValue
(und unterstützt das Roundtripping mitEnum.Parse
). Es lohnt sich auch oft, eine zuTypeConverter
erstellen, wie Steve Mitcham vorschlägt, um die UI-Bindung zu unterstützen. (Es ist nicht notwendig, eine zu bauenTypeConverter
wenn Sie Eigenschaftenblätter verwenden, was eines der schönen Dinge an Eigenschaftenblättern ist. Obwohl Lord weiß, dass sie ihre eigenen Probleme haben.)Wenn die Antworten auf die obigen Fragen darauf hindeuten, dass dies nicht funktionieren wird, besteht mein nächster Schritt im Allgemeinen darin, eine statische
Dictionary<MyEnum, string>
oder möglicherweise eine statische zu erstellen und zu füllenDictionary<Type, Dictionary<int, string>>
. Ich neige dazu, den Zwischenschritt zum Dekorieren des Codes mit Attributen zu überspringen, da normalerweise als nächstes die Notwendigkeit besteht, die benutzerfreundlichen Werte nach der Bereitstellung zu ändern (häufig, aber nicht immer, aufgrund der Lokalisierung).quelle
Ich wollte dies als Kommentar zu dem unten zitierten Beitrag posten, konnte es aber nicht, weil ich nicht genug Repräsentanten habe - bitte stimmen Sie nicht ab. Der Code enthielt einen Fehler, und ich wollte Personen, die versuchen, diese Lösung zu verwenden, darauf hinweisen:
sollte sein
Genial!
quelle
Meine Variante
Code sieht ein bisschen hässlich aus, aber die Verwendung dieser Struktur ist ziemlich präsentativ.
Ich denke auch, wenn viele solcher Aufzählungen erforderlich sind, könnte die Codegenerierung (z. B. T4) verwendet werden.
quelle
Option 1:
und dann
Option 2:
quelle
Wenn Sie über das Problem nachdenken, das wir zu lösen versuchen, ist es keine Aufzählung, die wir überhaupt brauchen. Wir brauchen ein Objekt, mit dem eine bestimmte Anzahl von Werten miteinander verknüpft werden kann. mit anderen Worten, um eine Klasse zu definieren.
Das typsichere Aufzählungsmuster von Jakub Šturc ist die beste Option, die ich hier sehe.
Schau es dir an:
quelle
Für mich ist der pragmatische Ansatz Klasse für Klasse, Beispiel:
quelle
Ich habe eine Basisklasse zum Erstellen von Aufzählungen mit Zeichenfolgen in .NET erstellt. Es ist nur eine C # -Datei, die Sie kopieren und in Ihre Projekte einfügen oder über das NuGet-Paket StringEnum installieren können . GitHub Repo
<completitionlist>
. (Funktioniert sowohl in C # als auch in VB)Installation:
.Net Standard 1.0
dass es auf.Net Core
> = 1.0,.Net Framework
> = 4.5,Mono
> = 4.6 usw. ausgeführt wird.quelle
Hier ist eine weitere Möglichkeit, die Aufgabe des Zuordnens von Zeichenfolgen zu Aufzählungen zu erfüllen:
Diese Methode heißt folgendermaßen:
Sie können verwandte Aufzählungen in ihrer eigenen Struktur gruppieren. Da diese Methode den Aufzählungstyp verwendet, können Sie mit Intellisense die Liste der Aufzählungen anzeigen, wenn Sie den
GetString()
Anruf tätigen .Sie können optional den neuen Operator für die
DATABASE
Struktur verwenden. Wenn Sie es nicht verwenden, werden die ZeichenfolgenList
erst beim erstenGetString()
Aufruf zugewiesen .quelle
Viele gute Antworten hier, aber in meinem Fall nicht gelöst, was ich von einer "String-Enumeration" wollte, die war:
1,2 & 4 können tatsächlich mit einem C # -Typedef eines Strings gelöst werden (da Strings in c # umschaltbar sind)
3 kann durch statische const-Strings gelöst werden. Wenn Sie also dieselben Anforderungen haben, ist dies der einfachste Ansatz:
Dies ermöglicht zum Beispiel:
und
Wobei CreateType mit einer Zeichenfolge oder einem Typ aufgerufen werden kann. Der Nachteil ist jedoch, dass jeder String automatisch eine gültige Aufzählung ist. Dies könnte geändert werden, aber dann würde es eine Art Init-Funktion erfordern ... oder sie explizit intern umwandeln?
Nun , wenn ein int - Wert für Dich wichtig ist (vielleicht für Vergleichsgeschwindigkeit), Sie könnten einige Ideen von Jakub Šturc fantastischer Antwort verwenden und etwas tun , ein bisschen verrückt, das ist mein Stab an sie:
aber natürlich "Types bob = 4;" wäre bedeutungslos, wenn Sie sie nicht zuerst initialisiert hätten, was den Punkt irgendwie zunichte machen würde ...
Aber theoretisch wäre TypeA == TypeB schneller ...
quelle
Wenn ich Sie richtig verstehe, können Sie einfach .ToString () verwenden, um den Namen der Aufzählung aus dem Wert abzurufen (vorausgesetzt, sie ist bereits als Aufzählung umgewandelt). Wenn Sie das nackte int hatten (sagen wir aus einer Datenbank oder so), können Sie es zuerst in die Enumeration umwandeln. Mit beiden Methoden erhalten Sie den Namen der Aufzählung.
Beachten Sie jedoch, dass bei der zweiten Technik davon ausgegangen wird, dass Sie Ints verwenden und Ihr Index auf 1 basiert (nicht auf 0). Die Funktion GetNames ist im Vergleich auch ziemlich umfangreich. Sie generieren bei jedem Aufruf ein ganzes Array. Wie Sie in der ersten Technik sehen können, wird .ToString () tatsächlich implizit aufgerufen. Beide sind natürlich bereits in den Antworten erwähnt, ich versuche nur, die Unterschiede zwischen ihnen zu klären.
quelle
alter Beitrag aber ...
Die Antwort darauf kann tatsächlich sehr einfach sein. Verwenden Sie die Funktion Enum.ToString ()
Es gibt 6 Überladungen dieser Funktion. Sie können Enum.Tostring ("F") oder Enum.ToString () verwenden, um den Zeichenfolgenwert zurückzugeben. Sie müssen sich um nichts anderes kümmern. Hier ist eine funktionierende Demo
Beachten Sie, dass diese Lösung möglicherweise nicht für alle Compiler funktioniert ( diese Demo funktioniert nicht wie erwartet ), aber zumindest für den neuesten Compiler.
quelle
basierend auf dem MSDN: http://msdn.microsoft.com/en-us/library/cc138362.aspx
str sind die Namen der Felder
quelle
Nun, nachdem ich all das oben Genannte gelesen habe, habe ich das Gefühl, dass die Jungs das Problem der Umwandlung von Enumeratoren in Strings überkompliziert haben. Ich mochte die Idee, Attribute über aufgezählte Felder zu haben, aber ich denke, dass Attribute hauptsächlich für Metadaten verwendet werden, aber in Ihrem Fall denke ich, dass alles, was Sie brauchen, eine Art Lokalisierung ist.
Wenn wir nun versuchen, die obige Methode aufzurufen, können wir sie so aufrufen
Sie müssen lediglich eine Ressourcendatei erstellen, die alle Enumeratorwerte und die entsprechenden Zeichenfolgen enthält
Das Schöne daran ist, dass es sehr hilfreich ist, wenn Ihre Anwendung lokalisiert werden muss, da Sie lediglich eine weitere Ressourcendatei mit Ihrer neuen Sprache erstellen müssen! und Voe-la!
quelle
Wenn ich in einer solchen Situation bin, schlage ich die folgende Lösung vor.
Und als konsumierende Klasse könnten Sie haben
Und Verwenden eines bidirektionalen Wörterbuchs: Basierend darauf ( https://stackoverflow.com/a/255638/986160 ) unter der Annahme, dass die Schlüssel einzelnen Werten im Wörterbuch zugeordnet werden und ähnlich wie ( https://stackoverflow.com/a) sind / 255630/986160 ), aber etwas eleganter. Dieses Wörterbuch ist auch aufzählbar und Sie können von Ints zu Strings hin und her gehen. Außerdem müssen Sie mit Ausnahme dieser Klasse keine Zeichenfolge in Ihrer Codebasis haben.
quelle
Bei größeren Saitensummen können die aufgeführten Beispiele lästig werden. Wenn Sie eine Liste von Statuscodes oder eine Liste anderer auf Zeichenfolgen basierender Aufzählungen wünschen, ist die Verwendung eines Attributsystems ärgerlich, und die Konfiguration einer statischen Klasse mit Instanzen von sich selbst ist ärgerlich. Für meine eigene Lösung verwende ich T4-Vorlagen, um das Erstellen von Aufzählungen mit Zeichenfolgen zu vereinfachen. Das Ergebnis ähnelt der Funktionsweise der HttpMethod-Klasse.
Sie können es so verwenden:
Sie beginnen mit einer Enum.tt-Datei.
Anschließend fügen Sie Ihre Datei StringEnum.ttinclude hinzu.
Schließlich kompilieren Sie Ihre Enum.tt-Datei neu und die Ausgabe sieht folgendermaßen aus:
quelle