Warum sind .NETTO-Wert-Typen versiegelt?
Es ist nicht möglich, Erben von einem C# struct. Es ist mir nicht klar, warum das so ist:
- Klar man kann nicht ein Referenz-Typ erbt von einem Wert-Typ; würde dies nicht funktionieren,
- Es klingt nicht vernünftig zu Erben von einem der primitiven Typen (Int32, Double, Char, etc).
- Sie müssten in der Lage sein zu rufen (nicht-virtuellen) Methoden auf der Basis einer abgeleiteten Instanz. Sie konnte Stimmen aus einem der abgeleiteten Struktur der base, da würden Sie sich den gleichen Speicher. Ich denke, eine Umwandlung von einer Basis abgeleitet würde nicht funktionieren, da Sie nicht wissen konnte, die Art der abgeleiteten Struktur zur Laufzeit.
- Ich kann sehen, dass Sie nicht implementieren die virtuellen Methoden in der Klassenhierarchie, da Wert-Typen können keine virtuellen Mitglieder
Frage ich mich, ob dies ist eine technische Einschränkung in der CLR, oder etwas, dass der C# - compiler nicht mehr tun?
Edit: Wert-Typen können nicht virtuelle Methoden, und ich begreife, dass diese Einschränkung Regeln, die meisten Szenarien, in denen Sie wollen, um die Vererbung verwenden. Dass noch die Blätter der Vererbung-als-aggregation, obwohl. Stellen Sie sich eine Shape
Struktur mit einer Colour
Feld: ich kann code schreiben, der nimmt eine beliebige struct abgeleitet von Shape
und auf Ihr Colour
Feld, auch wenn ich nie schreiben, ein virtuelles Shape.Draw
Methode.
Ich denken kann, ein Szenario, das bekommen würden, gebrochen durch die nicht versiegelten Wert-Typen. Wert-Typen sollen zu implementieren Equals
und GetHashCode
richtig; auch wenn diese beiden Methoden auf System.Object
virtuell sind, bekommen Sie als nicht-virtuell auf Wert-Typen. Auch wenn Werte-Typen waren nicht versiegelt, jemand schreiben, eine Struktur, die von einer anderen abgeleitet, könnte man gar nicht schreiben Ihre eigene Implementierung dieser beiden Methoden, und erwarten, dass Sie ordnungsgemäß aufgerufen.
Ich darauf hinweisen, dass ich bin nicht dafür, ich sollte in der Lage sein, die Vererbung von Strukturen in meinem eigenen code. Was ich versuche zu tun, obwohl, ist zu erraten, warum diese Besondere code, der Geruch ist verboten .NET.
Edit 2: ich habe gerade entdeckt diese sehr ähnlichen Frage, die Antwort auf die effektiv ", weil dann arrays von Werttypen nicht funktionieren würde".
- mögliche Duplikate von Warum nicht structs Vererbung unterstützt?
Du musst angemeldet sein, um einen Kommentar abzugeben.
Der Grund dafür ist, dass die meisten Vererbung Techniken beziehen sich auf Laufzeit-Polymorphie (virtuelle Funktionen) und diejenigen, die nicht auf Werte-Typen: für Laufzeit-Polymorphismus einen Sinn haben, Objekte, die behandelt werden müssen als Verweise – dies ist nicht spezifisch für .NET entweder, es ist einfach ein technisches detail, wie die virtuellen Funktionen sind implementiert.
Wert Arten bilden eine Ausnahme .NET die Regel, genau das zu ermöglichen leichten Objekte, die nicht brauchen Umweg über Referenzen. So Laufzeit-Polymorphismus nicht für Sie arbeiten und die meisten Aspekte der Vererbung bedeutungslos geworden.
(Es gibt eine Ausnahme: ein Wert vom Typ Objekt können geschachtelt werden, das es ermöglicht, virtuelle Methoden, geerbt von
System.Object
genannt zu werden.)Adresse einer deiner Punkte:
Nein, dies wäre nicht möglich – die Umwandlung eines Wertes geben würde kopieren seinen Wert. Wir sind nicht der Umgang mit Referenzen, so dass keine überschneidungen in den Speicher. Casting einen Wert geben, um Ihre Basis zu geben, ist daher bedeutungslos (wieder, es sei denn, wir reden über die Umstellung auf
object
die tatsächlich durchführt Boxen unter der Haube und auch arbeitet auf einer kopieren der Wert).Immer noch nicht klar? Betrachten wir ein Beispiel.
Sagen wir, wir haben den hypothetischen
struct Shape
und erbt von ihm, diestruct Circle
.Shape
definiert eine virtuelleDraw
Methode (das übernimmt einGraphics
Objekt). Nun, sagen wir, wir möchten, zeichnen Sie eine Form auf der Leinwand. Dies klappt natürlich sehr gut:– Aber hier sind wir nicht wirklich Vererbung überhaupt. Um die Verwendung der Vererbung, stellen Sie sich stattdessen folgende
DrawObject
Helfer-Methode:Wir nennen es anderswo mit einem
Circle
:– Und ka-blam – dieser code nicht, zeichnen Sie einen Kreis. Warum? Denn wenn wir an den Kreis, um die
DrawObject
Methode, die wir zwei Dinge tun:shape
Objekt ist wirklich nicht mehrCircle
– weder das original noch eine Kopie. StattdessenCircle
Teil wurde "in Scheiben geschnitten" Weg beim kopieren und nur dieShape
Teil bleibt.shape.Draw
jetzt ruft dieDraw
Methode derShape
, nicht vonCircle
.In C++, Sie können tatsächlich dazu führen, dass dieses Verhalten. Aus diesem Grund, OOP in C++ funktioniert nur bei Zeigern und Referenzen, nicht auf Wert-Typen direkt. Und aus dem gleichen Grund .NET nur erlaubt die Vererbung von Referenz-Typen, weil Sie nicht verwenden können, es für Wert-Typen sowieso.
Beachten Sie, dass der obige code hat arbeiten .Wenn NET
Shape
ist eine Schnittstelle. In anderen Worten, eine Referenz geben. Jetzt ist die situation anders: Ihrcircle
Objekt noch kopiert werden, sondern es werden auch boxed in einen Verweis.Nun .NET könnte theoretisch erlauben Sie Erben eine
struct
aus einerclass
. Dann würde der obige code funktioniert genauso gut, als wennShape
waren eine Schnittstelle. Aber dann hat das ganze den Vorteil einerstruct
in den ersten Platz verschwindet: für alle Absichten und Zwecke (außer für lokale Variablen, die nie weitergeleitet zu einer anderen Methode, daher auch kein nutzen von Vererbung) Ihrestruct
Verhalten würde als eine unveränderliche Referenz geben Sie anstelle des Wertes geben.Equals
. – Eh, Sie reden nur über code-Vererbung anstelle von interface-Vererbung dann. Code-Vererbung kann trivial umgesetzt, Zusammensetzung und der Konsens, der in der OO-community ist, dass Sie (fast?) immer zugunsten Komposition über Vererbung, wenn es um Wiederverwendung von code, da dies eigentlich eine Implementierung detail. Was andere Anwendungen von Vererbung habe ich vergessen?Object
virtuellen Methoden, aber der Wert, den der Typ selbst keine virtuellen Methoden. Beachten Sie, dassGetType
ist keine virtuelle Methode, aber es erfordert Boxen, da es untersucht versteckten "Typinformationen" Daten, die nur existiert für die Klasse instances.ToString
direkt auf die Strukturen ohne virtuelle Versand und ohne Boxen. Mit einem struct ist das überschreiben derObject.Equals
zu vergleichen Strukturen erfordert in der Regel Boxen der comparand (da der parameter vom TypObject
), nicht aber das Objekt, das die Vergleich.Von ECMA-335:
Wert-Typen werden versiegelt, um zu vermeiden, Umgang mit Komplikationen-Wert schneiden.
Die restriktiveren Regeln, die hier angegeben ermöglichen eine effiziente Umsetzung ohne schwer
Kompromisse bei der Funktionalität.
Ich weiß nicht, was 'Wert schneiden' bedeutet, aber ich würde vermuten, Sie sind versiegelt, um eine effiziente Implementierung der CLR.
Konnte man einige eingeschränkte form der Vererbung mit Hilfe von generischen Typ-Parameter Wert-Typen.
Da jede Instanz von Wert-Typ hase unterschiedlicher Größe und auf dem stack gespeichert werden. Also, wenn Sie schreiben, "Base = Derived" - wobei "Base" und "Abgeleitet" sind Wert-Typen, die Sie korrumpieren stack.