Par analogie, C # est fondamentalement comme un ensemble d'outils de mécanicien dans lequel quelqu'un a lu qu'il fallait généralement éviter les pinces et les clés à molette, de sorte qu'il n'inclut pas de clés à molette, et que les pinces sont verrouillées dans un tiroir spécial portant la mention "non sécurisé". , et ne peut être utilisé qu'avec l'approbation d'un superviseur, après avoir signé un désistement dégageant votre employeur de toute responsabilité vis-à-vis de votre santé.
C ++, en comparaison, comprend non seulement des clés et des pinces ajustables, mais également des outils spéciaux plutôt bizarres dont le but n'est pas immédiatement évident. Si vous ne connaissez pas la bonne façon de les tenir, ils risquent de vous couper facilement la main. thumb (mais une fois que vous avez compris comment les utiliser, vous pouvez faire des choses qui sont essentiellement impossibles avec les outils de base de la boîte à outils C #). En outre, il dispose d'un tour, d'une fraiseuse, d'une rectifieuse, d'une scie à ruban à métaux, etc., pour vous permettre de concevoir et de créer de tout nouveaux outils chaque fois que vous en ressentez le besoin (mais, oui, les outils de ces machinistes peuvent et vont causer blessures graves si vous ne savez pas ce que vous faites avec eux - ou même si vous ne faites pas attention à rien).
Cela reflète la différence fondamentale de philosophie: le C ++ tente de vous fournir tous les outils dont vous pourriez avoir besoin pour la conception de votre choix. Il ne fait pratiquement aucun effort pour contrôler la manière dont vous utilisez ces outils. Il est donc également facile de les utiliser pour créer des dessins qui ne fonctionnent bien que dans de rares situations, ainsi que des dessins qui ne sont probablement qu'une idée moche et que personne ne connaît. ils sont susceptibles de bien fonctionner. En particulier, une grande partie de cela est réalisée en découplant les décisions de conception - même celles qui, dans la pratique, sont presque toujours couplées. En conséquence, il y a une énorme différence entre juste écrire en C ++ et bien écrire en C ++. Pour bien écrire en C ++, vous devez connaître de nombreux idiomes et règles empiriques (y compris les règles empiriques expliquant comment reconsidérer sérieusement la situation avant d'enfreindre d'autres règles empiriques). Par conséquent, C ++ est beaucoup plus orienté vers la facilité d'utilisation (par les experts) que la facilité d'apprentissage. Il y a aussi (beaucoup trop) de cas dans lesquels il n'est pas vraiment facile à utiliser non plus.
C # fait beaucoup plus pour essayer de forcer (ou du moins très fortement suggérer) ce que les concepteurs de langage ont considéré comme de bonnes pratiques de conception. Un certain nombre de choses qui sont découplées en C ++ (mais vont généralement ensemble) sont directement couplées en C #. Cela permet au code "non sécurisé" de repousser légèrement les limites, mais honnêtement, pas beaucoup.
Il en résulte qu’un certain nombre de conceptions pouvant être exprimées assez directement en C ++ sont plus difficiles à exprimer en C #. D'autre part, il est un ensemble beaucoup plus facile à apprendre C #, et les chances de produire un design vraiment horrible qui ne fonctionnera pas pour votre situation (ou probablement tout autre) sont considérablement réduits. Dans de nombreux cas (probablement même dans la plupart des cas), vous pouvez obtenir une conception solide et réalisable simplement en "allant avec le courant", pour ainsi dire. Ou, comme l'un de mes amis (du moins j'aime le penser comme un ami - je ne sais pas s'il est vraiment d'accord) aime le dire, C # facilite la chute dans le gouffre du succès.
Donc, en regardant plus spécifiquement la question de savoir comment class
et struct
comment ils sont dans les deux langages: objets créés dans une hiérarchie d'héritage où vous pourriez utiliser un objet d'une classe dérivée sous le couvert de sa classe / interface de base, vous êtes à peu près coincé avec le fait que vous devez normalement le faire via une sorte de pointeur ou de référence - à un niveau concret, ce qui se passe est que l'objet de la classe dérivée contient quelque chose de mémoire qui peut être traitée comme une instance de la classe de base / l'interface, et l'objet dérivé est manipulé via l'adresse de cette partie de la mémoire.
En C ++, il appartient au programmeur de le faire correctement - lorsqu'il utilise l'héritage, il lui appartient de s'assurer que, par exemple, une fonction qui fonctionne avec des classes polymorphes dans une hiérarchie le fait via un pointeur ou une référence à la base. classe.
En C #, ce qui est fondamentalement la même séparation entre les types est beaucoup plus explicite et imposé par le langage lui-même. Le programmeur n'a pas besoin de passer à l'étape suivante pour passer une instance d'une classe par référence, car cela se produira par défaut.
struct
s ne sont pas toujours stockés sur la pile; considérons un objet avec unstruct
champ. Cela dit, comme l'a mentionné Mason Wheeler, le problème de découpage en tranches est probablement la principale raison.