Ich habe ein Problem mit Vererbung und Generika. Dies ist der Code, der mein Problem veranschaulicht:
%Vor%Und wenn ich versuche, so etwas zu tun:
%Vor%Ich erhalte Cast-Ausnahme: Ungültige Cast-Ausnahme. Kann 'TestApplication.MyClass'1 [System.Int32]' nicht in 'TestApplication.MyIntClass' umwandeln.
Außerdem kann ich keinen Darsteller erzeugen:
%Vor%weil: 'TestApplication.MyIntClass.implicitate-Operator TestApplication.MyIntClass (TestApplication.MyClass)': benutzerdefinierte Konvertierungen zu oder von einer Basisklasse sind nicht zulässig
Ich muss Guss wie oben beschrieben erstellen. Ich weiß nicht, warum ich nicht von einem Typ, der die Basisklasse ist, casten kann. Wie kann ich dieses Problem lösen? Vielen Dank im Voraus.
Bearbeiten
Danke für Ihre Antworten. Jetzt sehe ich, dass ich nicht von einer Basisklasse in abgeleitete Klasse konvertieren kann und ich sehe, dass es nichts mit Generika zu tun hat. Aber warum kann ich keine benutzerdefinierten Konvertierungen von einer Basisklasse erstellen? Ich habe eine Methode, die die Basisklasse zurückgibt. Ich bin in der Lage, eine Konvertierungsmethode zu definieren, aber die Erstellung eines Cast-Operators imho wäre eine bessere Lösung.
Sie können nur von einer Basisklasse in eine abgeleitete Klasse umwandeln, wenn das Objekt tatsächlich vom Typ abgeleitete Klasse ist. Ich meine, Sie können keine Instanz der Basis ( MyClass<int>
) in MyIntClass
umwandeln. Sie können es jedoch umwandeln, wenn es tatsächlich vom Typ MyIntClass
als MyClass<int>
-Instanz gespeichert wurde.
Angenommen:
%Vor% Wenn es erlaubt wäre, was wäre der Wert von bar.y
?
Tatsächlich ist die Konvertierung von Derived
in Base
überhaupt keine Konvertierung. Es teilt dem Compiler lediglich mit, dass die Variable vom Typ Base
auf ein Objekt vom Typ Derived
zeigen soll. Es ist möglich, da abgeleitet hat mehr oder gleiche Merkmale als Base
, was nicht anders herum ist.
Wenn Sie einen Konvertierungsoperator zwischen Basis- und abgeleiteten Klassen erstellen könnten, wäre der C # -Compiler nicht in der Lage, ihn von den für sie definierten integrierten Beziehungen zu unterscheiden. Aus diesem Grund können Sie keine Darstellungsoperatoren entlang von Vererbungshierarchien erstellen.
In den Kommentaren, die Sie gefragt haben:
Aber warum ist die Konvertierung von einer Basisklasse nicht erlaubt?
Einfach - es würde keinen Sinn ergeben. Betrachten Sie das Beispiel:
%Vor% Was glaubst du, würde dieses Programm ausgeben, vorausgesetzt, die Besetzung hat funktioniert? Noch schlimmer - stellen Sie sich vor, dass BaseClass
zwei untergeordnete Klassen hat - ChildClassA
und ChildClassB
. Soll das funktionieren?
ChildClassA A = neue ChildClassA (); Basisklasse bc = (Basisklasse) A; ChildClassB B = (ChildClassB) bc;
Dies würde effektiv erlauben, ChildClassA
Instanzen auf ChildClassB
zu setzen - völlig falsch.
Wie Mehrdad sagte, können Sie ein Objekt nicht verkleinern. Upcasting ist implizit, daher können Sie es nicht überschreiben.
Wie für den impliziten Operator können Sie immer noch einen Konstruktor in der abgeleiteten Klasse erstellen, der einen Parameter vom Typ baseclass empfängt.
Wenn Sie frei umwandeln müssen, definieren Sie die Variable als baseclass, instanziieren Sie abgeleitete Klassen.
Wie bereits gesagt, versuchen Sie, ein Objekt in einen Typ umzuwandeln, von dem es nicht abgeleitet ist. Wolltest du das vielleicht machen?
%Vor%Bezüglich Ihrer zweiten Frage:
Aber warum kann ich keine benutzerdefinierten Konvertierungen von einer Basisklasse erstellen?
Nehmen wir an, Sie haben dieses Szenario
%Vor%und du hast das versucht
%Vor% sollte die Umwandlung aufgerufen werden? Natürlich nicht! Der Wert in x
ist vom Typ Derived
, also ist die Umwandlung direkt, ohne Konvertierung. Aber wenn der Wert nicht vom Typ Derived
ist, sondern von einem konkreten Base
, dann muss die benutzerdefinierte Konvertierung durchgeführt werden, da wir andernfalls einen Compilerfehler haben würden. Das alles macht keinen Sinn; Benutzerdefinierte Konvertierungen werden in der Kompilierungszeit gefunden, und der Typ des Werts von x
ist nur in Laufzeit bekannt. Daher weiß der Compiler nicht, was zu tun ist - rufen Sie die benutzerdefinierte Konvertierung auf oder geben Sie einfach den Wert ein ...
Ich hoffe, das macht für Sie etwas Sinn.
Beantworten Sie Ihre letzte Bearbeitung.
Dieser Code kompiliert bereits, er schlägt nur zur Laufzeit fehl:
MyIntClass intsth = (MyIntClass) etw;
Der folgende Umwandlungsoperator wäre also redundant, wenn explizit angegeben:
Öffentlicher statischer impliziter Operator MyIntClass (MyClass myClass)
Der Compiler sollte also verhindern, dass Sie diese Konvertierung hinzufügen. Ich denke, der Fehler mag verwirrend sein, aber ich denke, es verbietet es einfach, Klasse B in Klasse A umzuwandeln, wenn B von A abgeleitet ist (die Warnung schien mir zu verhindern, dass man zu A konvertiert).
Wenn der Operator implizit gemacht wird, ist das auch gefährlich, weil ein Downcasting immer fehlschlagen kann, also müssen Sie:
Die Zuweisung / Konvertierung einer Basisklasse in eine abgeleitete Klasse ist sinnvoll, wenn Sie die Zuordnung oder Konvertierung als wertweisen Kopieren betrachten. Was ist verwirrend an c #? Neulinge ist die inkonsequente Art, wie es Dinge tut:
Wenn es eine Kopie von Werten würde, würde das Kopieren in die Basisklasse in eine abgeleitete Klasse erfolgen Arbeit. C # funktioniert nicht wie andere Sprachen.
Ich denke, das könnte Sie verwirren.
Tags und Links c# inheritance generics casting