Ich habe eine Aufzählung in einem niedrigen Namespace. Ich möchte eine Klasse oder Aufzählung in einem Namespace mittlerer Ebene bereitstellen, die die Aufzählung niedriger Ebene "erbt".
namespace low
{
public enum base
{
x, y, z
}
}
namespace mid
{
public enum consume : low.base
{
}
}
Ich hoffe, dass dies möglich ist, oder vielleicht eine Art Klasse, die den Platz des Enum-Verbrauchs einnehmen kann, der eine Abstraktionsebene für das Enum bereitstellt, aber dennoch eine Instanz dieser Klasse auf das Enum zugreifen lässt.
Gedanken?
BEARBEITEN: Einer der Gründe, warum ich dies nicht nur auf Konstanten in Klassen umgestellt habe, ist, dass die Aufzählung auf niedriger Ebene von einem Dienst benötigt wird, den ich nutzen muss. Ich habe die WSDLs und die XSDs erhalten, die die Struktur als Aufzählung definieren. Der Dienst kann nicht geändert werden.
Antworten:
Das ist nicht möglich. Aufzählungen können nicht von anderen Aufzählungen erben. Tatsächlich müssen alle Aufzählungen tatsächlich von erben
System.Enum
. Mit C # kann die Syntax die zugrunde liegende Darstellung der Enum-Werte ändern, die wie Vererbung aussieht, in Wirklichkeit aber immer noch von System.enum erbt.Ausführliche Informationen finden Sie in Abschnitt 8.5.2 der CLI-Spezifikation . Relevante Informationen aus der Spezifikation
System.Enum
quelle
switch
Umständen nicht verwendet werden.Mit Klassen können Sie erreichen, was Sie wollen:
Jetzt können Sie diese Klassen ähnlich wie bei Aufzählungen verwenden:
Update (nach dem Update der Frage):
Wenn Sie den Konstanten dieselben int-Werte zuweisen, wie sie in der vorhandenen Aufzählung definiert sind, können Sie zwischen der Aufzählung und den Konstanten umwandeln, z.
quelle
Enum.GetValues(typeof(MyEnum)
void Test() { foreach (System.Reflection.PropertyInfo pi in typeof(Consume).GetProperties()) { Console.WriteLine(pi.Name); } }
Die kurze Antwort lautet nein. Sie können ein bisschen spielen, wenn Sie wollen:
Sie können immer so etwas tun:
Aber es funktioniert nicht so gut, weil Base.A! = Consume.A
Sie können jedoch immer so etwas tun:
Um zwischen Basis und Verbrauch zu wechseln ...
Sie können die Werte der Aufzählungen auch als Ints umwandeln und sie als Ints anstelle von Enum vergleichen, aber diese Art ist auch scheiße.
Die Rückgabe der Erweiterungsmethode sollte den Typ cast it type T geben.
quelle
Base.A == (Base)Consume.A
int
würde viel mehr Sinn machen. Wann würde eine Aufzählung einen Bruchteil haben!?!?!Die obigen Lösungen unter Verwendung von Klassen mit int-Konstanten sind nicht typsicher. Das heißt, Sie könnten neue Werte erfinden, die in der Klasse eigentlich nicht definiert sind. Darüber hinaus ist es beispielsweise nicht möglich, eine Methode zu schreiben, die eine dieser Klassen als Eingabe verwendet.
Sie müssten schreiben
Es gibt jedoch eine klassenbasierte Lösung der alten Java-Zeiten, als keine Aufzählungen verfügbar waren. Dies liefert ein fast enumartiges Verhalten. Die einzige Einschränkung ist, dass diese Konstanten nicht in einer switch-Anweisung verwendet werden können.
quelle
object
, würde die Werte für jede Instanziierung der Assembly unterschiedlich machen, sodass sie nicht serialisiert werden können.Wenn Sie die Tatsache ignorieren, dass base ein reserviertes Wort ist, können Sie die Aufzählung nicht vererben.
Das Beste, was Sie tun können, ist so etwas:
Da sie alle denselben Basistyp haben (dh: int), können Sie den Wert einer Instanz eines Typs dem anderen zuweisen, den eine Besetzung enthält. Nicht ideal, aber es funktioniert.
quelle
Ich weiß, dass diese Antwort etwas spät ist, aber das habe ich letztendlich getan:
Dann kann ich Dinge tun wie:
quelle
Das habe ich getan. Was ich anders gemacht habe, ist, den gleichen Namen und das
new
Schlüsselwort für das "Konsumieren" zu verwendenenum
. Da der Name desenum
gleich ist, können Sie ihn einfach sinnlos verwenden und es wird richtig sein. Außerdem bekommst du Intellisense. Sie müssen beim Einrichten nur manuell darauf achten, dass die Werte von der Basis kopiert und synchronisiert werden. Sie können dies zusammen mit Codekommentaren helfen. Dies ist ein weiterer Grund, warumenum
ich in der Datenbank beim Speichern von Werten immer die Zeichenfolge und nicht den Wert speichere. Denn wenn Sie automatisch zugewiesene ansteigende Ganzzahlwerte verwenden, können sich diese im Laufe der Zeit ändern.quelle
SmallMedium = 100,
), damit Sie die Kompatibilität mit älteren Versionen Ihrer Software beibehalten können, wenn Sie der Basisklasse neue Werte hinzufügen. Wenn Sie beispielsweise eineHuge
Größe in Ihre Basisaufzählung aufnehmen, wird4
diese ihrem Wert zugewiesen , wird jedoch4
bereits vonSmallMedium
der abgeleiteten Klasse übernommen.Huge
in der Basisklasse würde also einHuge
in der Unterklasse vorSmallMedium
BaseBall
ist hier vielleicht nicht der klügste Name. Es ist verwirrend. Da ist ein Baseball eigentlich eine Sache. Wenn Sie vermissen, dass dies nur eine Basisklasse für Ball ist, sieht es sehr seltsam aus, dass ein Volleyball von einem physisch kleineren Baseball erbt :). Mein Vorschlag ist, nur zu verwendenBall
Alternative Lösung
In meiner Firma vermeiden wir es, über Projekte zu springen, um zu nicht üblichen Projekten auf niedrigerer Ebene zu gelangen. Beispielsweise kann unsere Präsentations- / API-Schicht nur auf unsere Domänenschicht verweisen, und die Domänenschicht kann nur auf die Datenschicht verweisen.
Dies ist jedoch ein Problem, wenn es Aufzählungen gibt, auf die sowohl von der Präsentations- als auch von der Domänenschicht verwiesen werden muss.
Hier ist die Lösung, die wir (bisher) implementiert haben. Es ist eine ziemlich gute Lösung und funktioniert gut für uns. Die anderen Antworten waren rundum zutreffend.
Die Grundvoraussetzung ist, dass Aufzählungen nicht vererbt werden können - Klassen jedoch. Damit...
Dann, um die Aufzählungen in einem anderen übergeordneten Projekt zu "erben" ...
Das hat drei echte Vorteile ...
Um auf die Aufzählungen im ersten Projekt zu verweisen , können Sie das Präfix der Klasse verwenden: BaseEnums.StatusType.Pending oder ein "using static BaseEnums" hinzufügen. Aussage zu Ihren Nutzungen.
Im zweiten Projekt konnte ich jedoch beim Umgang mit der geerbten Klasse den Ansatz "using static ..." nicht zum Laufen bringen, sodass allen Verweisen auf die "geerbten Aufzählungen" die Klasse vorangestellt wurde, z. B. SubEnums.StatusType.Pending . Wenn jemand eine Möglichkeit findet, die Verwendung des statischen Ansatzes im zweiten Projekt zuzulassen , lassen Sie es mich wissen.
Ich bin sicher, dass dies optimiert werden kann, um es noch besser zu machen - aber das funktioniert tatsächlich und ich habe diesen Ansatz in Arbeitsprojekten verwendet.
Bitte stimmen Sie dies ab, wenn Sie es hilfreich finden.
quelle
Ich wollte auch Enums überladen und erstellte eine Mischung aus der Antwort von 'Seven' auf dieser Seite und der Antwort von 'Merlyn Morgan-Graham' auf einem doppelten Beitrag davon sowie ein paar Verbesserungen.
Hauptvorteile meiner Lösung gegenüber den anderen:
Dies ist eine sofort einsatzbereite Lösung, die direkt in Ihr Projekt eingefügt werden kann. Es ist auf meine Bedürfnisse zugeschnitten. Wenn Ihnen einige Teile davon nicht gefallen, ersetzen Sie sie einfach durch Ihren eigenen Code.
Erstens gibt es die Basisklasse
CEnum
, von der alle benutzerdefinierten Aufzählungen erben sollen. Es hat die Grundfunktionalität, ähnlich dem .net-Enum
Typ:Zweitens sind hier 2 abgeleitete Enum-Klassen. Alle abgeleiteten Klassen benötigen einige grundlegende Methoden, um wie erwartet zu arbeiten. Es ist immer der gleiche Boilerplate-Code. Ich habe noch keinen Weg gefunden, es an die Basisklasse auszulagern. Der Code der ersten Vererbungsstufe unterscheidet sich geringfügig von allen nachfolgenden Ebenen.
Die Klassen wurden erfolgreich mit folgendem Code getestet:
quelle
Aufzählungen sind keine tatsächlichen Klassen, auch wenn sie so aussehen. Intern werden sie genauso behandelt wie ihr zugrunde liegender Typ (standardmäßig Int32). Daher können Sie dies nur tun, indem Sie einzelne Werte von einer Aufzählung in eine andere "kopieren" und in ihre Ganzzahl umwandeln, um sie auf Gleichheit zu vergleichen.
quelle
Aufzählungen können nicht von anderen Aufzählungen abgeleitet werden, sondern nur von int, uint, short, ushort, long, ulong, byte und sbyte.
Wie Pascal sagte, können Sie die Werte oder Konstanten anderer Aufzählungen verwenden, um einen Aufzählungswert zu initialisieren, aber das war es auch schon.
quelle
eine andere mögliche Lösung:
HTH
quelle
Dies ist nicht möglich (wie bereits erwähnt bei @JaredPar). Der Versuch, die Logik zu umgehen, ist eine schlechte Praxis. Wenn Sie eine
base class
habenenum
, die eine haben , sollten Sie alle möglichen auflistenenum-values
dort auflisten, und die Implementierung der Klasse sollte mit den Werten arbeiten, die sie kennt.Angenommen, Sie haben eine Basisklasse
BaseCatalog
und sie hat einenum ProductFormats
(Digital
,Physical
). Dann können Sie einMusicCatalog
oder habenBookCatalog
, das sowohlDigital
als auchPhysical
ProdukteClothingCatalog
enthältPhysical
. Wenn die Klasse jedoch ist , sollte sie nur Produkte enthalten.quelle
Mir ist klar, dass ich etwas spät zu dieser Party komme, aber hier sind meine zwei Cent.
Wir sind uns alle darüber im Klaren, dass die Enum-Vererbung vom Framework nicht unterstützt wird. In diesem Thread wurden einige sehr interessante Problemumgehungen vorgeschlagen, aber keine davon fühlte sich so an, wie ich gesucht hatte, also habe ich es selbst ausprobiert.
Wir stellen vor: ObjectEnum
Sie können den Code und die Dokumentation hier überprüfen: https://github.com/dimi3tron/ObjectEnum .
Und das Paket hier: https://www.nuget.org/packages/ObjectEnum
Oder installieren Sie es einfach:
Install-Package ObjectEnum
Zusamenfassend,
ObjectEnum<TEnum>
fungiert als Wrapper für jede Aufzählung. Durch Überschreiben von GetDefinedValues () in Unterklassen kann angegeben werden, welche Aufzählungswerte für diese bestimmte Klasse gültig sind.Eine Anzahl von Bedienerüberladungen wurde hinzugefügt, um eine
ObjectEnum<TEnum>
Instanz so verhält, als wäre sie eine Instanz der zugrunde liegenden Aufzählung, wobei die definierten Werteinschränkungen berücksichtigt werden. Dies bedeutet, dass Sie die Instanz einfach mit einem int- oder enum-Wert vergleichen und somit in einem Switch-Fall oder einer anderen Bedingung verwenden können.Ich möchte auf das oben erwähnte Github-Repo für Beispiele und weitere Informationen verweisen.
Ich hoffe, Sie finden das nützlich. Fühlen Sie sich frei zu kommentieren oder ein Problem auf Github für weitere Gedanken oder Kommentare zu öffnen.
Hier sind einige kurze Beispiele dafür, was Sie tun können
ObjectEnum<TEnum>
:quelle
Sie können die Vererbung in enum durchführen, sie ist jedoch nur auf folgende Typen beschränkt. int, uint, byte, sbyte, kurz, kurz, lang, ulong
Z.B
quelle