Por analogía, C # es básicamente como un conjunto de herramientas mecánicas en las que alguien ha leído que generalmente debe evitar los alicates y las llaves ajustables, por lo que no incluye llaves ajustables, y los alicates están bloqueados en un cajón especial marcado como "inseguro" , y solo se puede usar con la aprobación de un supervisor, después de firmar un descargo de responsabilidad que exime a su empleador de cualquier responsabilidad por su salud.
C ++, en comparación, no solo incluye llaves y alicates ajustables, sino también algunas herramientas de propósito especial bastante extrañas cuyo propósito no es evidente de inmediato, y si no conoce la forma correcta de sostenerlas, podrían cortar fácilmente su thumb (pero una vez que comprenda cómo usarlos, puede hacer cosas que son esencialmente imposibles con las herramientas básicas en la caja de herramientas de C #). Además, tiene un torno, una fresadora, una amoladora de superficie, una sierra de cinta para corte de metales, etc., que le permite diseñar y crear herramientas completamente nuevas cada vez que lo necesite (pero sí, esas herramientas de maquinista pueden causar y causarán lesiones graves si no sabe lo que está haciendo con ellas, o incluso si simplemente se descuida).
Eso refleja la diferencia básica en filosofía: C ++ intenta darle todas las herramientas que pueda necesitar para esencialmente cualquier diseño que desee. Casi no intenta controlar cómo usa esas herramientas, por lo que también es fácil usarlas para producir diseños que solo funcionan bien en situaciones raras, así como diseños que probablemente son solo una mala idea y nadie sabe de una situación en la que Es probable que funcionen bien. En particular, gran parte de esto se hace desacoplando las decisiones de diseño, incluso aquellas que en la práctica realmente casi siempre están acopladas. Como resultado, hay una gran diferencia entre simplemente escribir C ++ y escribir bien C ++. Para escribir bien C ++, debe conocer muchas expresiones idiomáticas y reglas generales (incluidas las reglas generales acerca de la seriedad de reconsiderar antes de romper otras reglas generales). Como resultado, C ++ está orientado mucho más a la facilidad de uso (por expertos) que a la facilidad de aprendizaje. También hay (demasiadas) circunstancias en las que tampoco es muy fácil de usar.
C # hace mucho más para tratar de forzar (o al menos sugerir extremadamente ) lo que los diseñadores de lenguaje consideraron buenas prácticas de diseño. Algunas cosas que están desacopladas en C ++ (pero que generalmente van juntas en la práctica) se acoplan directamente en C #. Sí permite que el código "inseguro" empuje un poco los límites, pero honestamente, no mucho.
El resultado es que, por un lado, hay bastantes diseños que se pueden expresar de manera bastante directa en C ++ que son mucho más torpes de expresar en C #. Por otro lado, se trata de un conjunto mucho más fácil de aprender C #, y las posibilidades de producir un diseño realmente horrible que no funcionará para su situación (o probablemente cualquier otro) están drásticamente reducida. En muchos (probablemente incluso en la mayoría de los casos), puede obtener un diseño sólido y viable simplemente "siguiendo la corriente", por así decirlo. O, como a uno de mis amigos (al menos me gusta pensar en él como un amigo, no estoy seguro de si realmente está de acuerdo) le gusta decirlo, C # hace que sea fácil caer en el pozo del éxito.
Entonces, mirando más específicamente la cuestión de cómo class
y struct
cómo se encuentran en los dos idiomas: objetos creados en una jerarquía de herencia en la que podría usar un objeto de una clase derivada bajo la apariencia de su clase / interfaz base, está bastante atascado con el hecho de que normalmente necesita hacerlo a través de algún tipo de puntero o referencia: en un nivel concreto, lo que sucede es que el objeto de la clase derivada contiene algo de memoria que puede tratarse como una instancia de la clase base / interfaz, y el objeto derivado se manipula a través de la dirección de esa parte de la memoria.
En C ++, depende del programador hacer eso correctamente; cuando usa la herencia, depende de él asegurarse de que (por ejemplo) una función que funciona con clases polimórficas en una jerarquía lo haga mediante un puntero o una referencia a la base clase.
En C #, lo que es fundamentalmente la misma separación entre los tipos es mucho más explícito y el propio lenguaje lo impone. El programador no necesita dar ningún paso para pasar una instancia de una clase por referencia, porque eso sucederá de manera predeterminada.
struct
s no siempre se almacenan en la pila; considere un objeto con unstruct
campo. Aparte de eso, como Mason Wheeler mencionó, el problema del corte es probablemente la razón más importante.