Angenommen, ich habe eine generische abstrakte Klasse, die einige Standardfunktionen für Konstruktoren bietet, sodass Sie den Code in Ihren geerbten Klassen nicht wiederholen müssen:
%Vor%Nun ist das Problem, wenn ich zwei vererbte Klassen schreibe:
%Vor%Wie Sie sehen können, sind diese beiden Arten wirklich typsichere Aufzählungen. Sie bieten nur vordefinierte Werte und können nicht für andere Zwecke instanziiert werden.
Das Problem liegt daran, dass beide geerbten Klassen die gleichen generischen Typen mit der Basisklasse Base<string, string>
verwenden. Und die Art und Weise, wie generische Klassen und statische Felder funktionieren, ist die, dass für jeden generischen Typ (oder eine Kombination aus mehreren) ein neues statisches Feld erstellt wird.
In meinem Fall ist die Kombination string, string
, deshalb gibt es nur ein statisches Basisklassenfeld und es enthält 4 Werte, anstatt zwei statische Felder mit jeweils zwei Werten .
Wie kann ich dieses Problem lösen und diese trennen, während diese Funktionalität weiterhin in der Basisklasse hält , damit ich meinen Code nicht wiederhole?
Das Ändern des Felds von "static" in "instance" funktioniert nicht, weil sie 4 Instanzen mit jeweils nur einem Wert ergeben ...
Das Problem tritt natürlich auf, weil Ihre zwei Klassen dieselbe Basisklasse mit den gleichen generischen Typargumenten verwenden. Dies bedeutet, dass sie die gleichen statischen Mitglieder teilen.
Wie überwinde ich dieses Problem und trenne es unter Beibehaltung dieser Funktionalität in der Basisklasse, damit ich meinen Code nicht wiederhole?
Ein Ansatz wäre, Ihr Dictionary in einem Wörterbuch zu erstellen, das auf dem aktuellen Laufzeittyp basiert:
%Vor%Dies führt dazu, dass alle Nachschlagevorgänge zwei Phasen haben, da Sie den aktuellen Typ suchen müssen dann den Wert in diesem Wörterbuch nachschlagen, aber er ist nicht darauf angewiesen, Ihre Unterklassen-API überhaupt zu ändern.
Dies beantwortet die Frage nicht direkt, sondern bietet stattdessen ein alternatives Design, um hoffentlich das gleiche Ziel zu erreichen.
Es scheint mir, als ob Sie versuchen, eine Basisklasse für etwas zu verwenden, das kein Basisverhalten oder zumindest kein statisches Verhalten ist.
Trennen Sie die Bedenken, eine Nachschlageliste item zu sein, und geben Sie die Nachschlagelistenreferenz an.
Wenn Sie versuchen, bekannte Lookups bereitzustellen, würde ich den Lookup-Listenreferenz getrennt von den Lookup-Elementen (wie in, nicht ein statisches Mitglied):
%Vor%Dann kann jeder Typ einfach auf das entsprechende Wörterbuch zeigen, oder es benennen und durch Reflexion darauf zugreifen oder einen Func bereitstellen:
%Vor%Damit können Sie auch die Liste selbst von den Elementen in der Liste trennen (vielleicht durch Injektion).
Beachten Sie auch, dass, wenn die Basisklasseninstanzen einen Verweis auf dieselben Wörterbücher haben, das Mitglied nicht statisch sein muss.
Dies ist beabsichtigt. Ein statisches Member hat nur eine Kopie in allen Instanzen und ein statisches Member in einer Basisklasse hat nur eine Kopie in allen Instanzen aller Unterklassen.
Warum bist du statisch? Möchten Sie, dass alle Instanzen von One ein gemeinsames Wörterbuch gemeinsam verwenden?
Wenn Sie möchten, dass Einer über andere teilt, aber nicht mit Twos teilt, müssen Sie Ihr Design ändern. Machen Sie es entweder nicht statisch (was keine Freigabe verursacht) oder statisch auf der Ebene jeder Unterklasse.
Mache eine abstrakte Methode / Eigenschaft in der Basisklasse und überschreibe sie in den Unterklassen, wenn du die API zwischen ihnen halten möchtest
Machen Sie Ihre Basis anders.
%Vor%UPDATE: Nach der Veröffentlichung bemerkte ich mehr oder weniger die gleiche Antwort wurde bereits gegeben, aber beachten Sie den Unterschied: die Einschränkung für den Typ T und die Verwendung von T in der Wörterbuchdefinition. Es ist nicht dumm, aber es hilft.
Die Umwandlung in T muss das Objekt zum Wörterbuch hinzufügen können. Beachten Sie, dass ich eine explizite Umwandlung und nicht den Operator as
verwende. Bei falscher Verwendung würde der Operator as
eine Null in das Wörterbuch einfügen, wo der Cast ihn (wie es sollte) brechen sollte.
Aber auch: Ссылка
Tags und Links c# inheritance generics static