Analog ist C # im Grunde genommen wie ein Satz von Mechanikerwerkzeugen, bei denen jemand gelesen hat, dass Sie Zangen und verstellbare Schraubenschlüssel generell vermeiden sollten, so dass verstellbare Schraubenschlüssel überhaupt nicht enthalten sind und die Zangen in einer speziellen Schublade mit der Kennzeichnung "unsicher" verriegelt sind. , und können nur mit Zustimmung eines Vorgesetzten verwendet werden, nachdem ein Haftungsausschluss unterzeichnet wurde, der Ihren Arbeitgeber von jeglicher Verantwortung für Ihre Gesundheit entbindet.
Im Vergleich dazu enthält C ++ nicht nur verstellbare Schraubenschlüssel und Zangen, sondern auch einige Sonderwerkzeuge, deren Zweck nicht sofort ersichtlich ist. Wenn Sie nicht wissen, wie Sie sie richtig halten können, können sie Ihnen leicht die Hand nehmen Daumen (aber wenn Sie erst einmal wissen, wie man sie benutzt, können Sie mit den grundlegenden Werkzeugen in der C # -Toolbox Dinge tun, die im Grunde unmöglich sind). Darüber hinaus gibt es eine Drehmaschine, Fräsmaschine, Flachschleifmaschine, Metallbandsäge usw., mit denen Sie jederzeit ganz neue Werkzeuge entwerfen und herstellen können, wenn Sie dies für erforderlich halten (aber ja, die Werkzeuge dieser Maschinisten können und werden dies bewirken Schwere Verletzungen, wenn Sie nicht wissen, was Sie mit ihnen machen - oder wenn Sie einfach nur nachlässig werden.
Dies spiegelt den grundlegenden Unterschied in der Philosophie wider: C ++ versucht, Ihnen alle Werkzeuge zur Verfügung zu stellen, die Sie für praktisch jedes gewünschte Design benötigen. Es wird fast kein Versuch unternommen, zu steuern, wie Sie diese Werkzeuge verwenden. Daher ist es auch einfach, mit ihnen Entwürfe zu erstellen, die nur in seltenen Situationen gut funktionieren, und Entwürfe, die wahrscheinlich nur eine schlechte Idee sind und von denen niemand weiß, in welcher Situation Sie werden wahrscheinlich überhaupt gut funktionieren. Insbesondere wird ein Großteil davon durch die Entkopplung von Entwurfsentscheidungen erzielt - auch wenn diese in der Praxis fast immer gekoppelt sind. Infolgedessen gibt es einen großen Unterschied zwischen dem einfachen Schreiben von C ++ und dem guten Schreiben von C ++. Um C ++ gut zu schreiben, müssen Sie eine Menge Redewendungen und Faustregeln kennen (einschließlich Faustregeln, wie ernst es ist, sie zu überdenken, bevor Sie andere Faustregeln brechen). Als Ergebnis, C ++ orientiert sich viel mehr an der Benutzerfreundlichkeit (von Experten) als an der Leichtigkeit des Lernens. Es gibt auch (allzu viele) Umstände, unter denen es auch nicht wirklich schrecklich einfach ist, es zu benutzen.
C # unternimmt noch viel mehr, um zu erzwingen (oder zumindest äußerst deutlich vorzuschlagen), was die Sprachdesigner als gute Entwurfspraktiken erachteten. Nicht wenige Dinge, die in C ++ entkoppelt sind (aber in der Praxis normalerweise zusammenpassen), sind in C # direkt gekoppelt. Es erlaubt "unsicherem" Code, die Grenzen ein wenig zu verschieben, aber ehrlich gesagt nicht viel.
Das Ergebnis ist, dass es auf der einen Seite einige Designs gibt, die ziemlich direkt in C ++ ausgedrückt werden können und in C # wesentlich ungeschickter auszudrücken sind. Auf der anderen Seite ist es eine ganze Menge einfacher C #, und die Chancen zur Herstellung ein wirklich schreckliches Designs , die Arbeit für Ihre Situation nicht lernen (oder wahrscheinlich andere) werden drastisch reduziert. In vielen (wahrscheinlich sogar den meisten) Fällen können Sie ein solides, funktionsfähiges Design erhalten, indem Sie sozusagen "im Fluss" bleiben. Oder, als einer meiner Freunde (zumindest ich sehe ihn gerne als Freund - nicht sicher, ob er wirklich einverstanden ist), macht es C # leicht, in die Grube des Erfolgs zu fallen.
Wenn Sie sich also genauer mit der Frage befassen, wie class
und struct
wie sie sich in den beiden Sprachen befinden: Objekte, die in einer Vererbungshierarchie erstellt wurden, in der Sie möglicherweise ein Objekt einer abgeleiteten Klasse als Basisklasse / Schnittstelle verwenden, sind Sie ziemlich fertig stecken geblieben mit der Tatsache, dass Sie dies normalerweise über einen Zeiger oder eine Referenz tun müssen - auf einer konkreten Ebene passiert, dass das Objekt der abgeleiteten Klasse etwas Gedächtnis enthält, das als eine Instanz der Basisklasse behandelt werden kann / Schnittstelle, und das abgeleitete Objekt wird über die Adresse dieses Teils des Speichers manipuliert.
In C ++ ist es Sache des Programmierers, dies korrekt zu tun. Wenn er die Vererbung verwendet, muss er sicherstellen, dass (zum Beispiel) eine Funktion, die mit polymorphen Klassen in einer Hierarchie arbeitet, dies über einen Zeiger oder einen Verweis auf die Basis tut Klasse.
In C # ist die grundsätzlich gleiche Trennung zwischen den Typen viel eindeutiger und wird von der Sprache selbst erzwungen. Der Programmierer muss keine Schritte ausführen, um eine Instanz einer Klasse als Referenz zu übergeben, da dies standardmäßig geschieht.
struct
s nicht immer auf dem Stapel gespeichert. Betrachten Sie ein Objekt mit einemstruct
Feld. Davon abgesehen, wie Mason Wheeler erwähnte, ist das Problem des Aufschneidens wahrscheinlich der größte Grund.