Tengo formación en C++ y entiendo perfectamente y estoy de acuerdo con las respuestas a esta pregunta: ¿Por qué se considera una mala práctica "using namespace std;"?
Así que me asombra que, teniendo ahora algo de experiencia con C#, vea allí exactamente lo contrario:
using Some.Namespace;
se utiliza literalmente en todas partes. Siempre que empiezas a usar un tipo, añades primero una directiva using para su espacio de nombres (si no está ya ahí). No recuerdo haber visto un archivo .cs
que no empezara con using System; using System.Collections.Generic; using X.Y.Z; etc...
.
De hecho, si añades un nuevo archivo a través del asistente de Visual Studio, automáticamente añade algunas directivas using, aunque no las necesites. Así que, mientras que en la comunidad C++ te linchan básicamente, C# incluso anima a hacer esto. Al menos así me parece a mí.
Ahora bien, entiendo que el uso de directivas en C# y en C++ no es exactamente lo mismo. También entiendo que una de las cosas más desagradables que se pueden hacer con el "uso de espacios de nombres" en C++, es decir, ponerlo en un archivo de cabecera, no tiene una contrapartida igual de desagradable en C# debido a la falta de un concepto de archivos de cabecera y "#include".
Sin embargo, a pesar de sus diferencias, el uso de directivas en C# y en C++ sirve para el mismo propósito, que es sólo tener que escribir AlgúnTipo
todo el tiempo, en lugar del mucho más largo Algún.EspacioDeNombres.AlgúnTipo
(en C++ con ::
en lugar de .
). Y con este mismo propósito, también el peligro me parece el mismo: colisiones de nombres.
En el mejor de los casos, esto resulta en un error de compilación, por lo que "sólo" tiene que arreglarlo. En el peor de los casos, sigue compilando y el código hace silenciosamente cosas diferentes a las que pretendías. Así que mi pregunta es: ¿Por qué (aparentemente) se considera que el uso de directivas es tan malo en C# y en C++?
Algunas ideas de respuesta que tengo (aunque ninguna me satisface realmente):
Los espacios de nombres tienden a ser mucho más largos y mucho más anidados en C# que en C++ (std
vs. System.Collection.Generic
). Por lo tanto, hay más ganas y más ganancia en desanclar el código de esta manera. Pero incluso si esto es cierto, este argumento sólo se aplica cuando nos fijamos en los espacios de nombres estándar. Los personalizados pueden tener cualquier nombre corto que se desee, tanto en C# como en C++.
Los espacios de nombres parecen ser mucho más "finamente granulares" en C# que en C++. Por ejemplo, en C++ toda la biblioteca estándar está contenida en std
(además de algunos pequeños espacios de nombres anidados como chrono
) mientras que en C# tienes System.IO
, System.Threading
, System.Text
etc. Por lo tanto, el riesgo de tener colisiones de nombres es menor. Sin embargo, esto es sólo una intuición. En realidad no conté cuántos nombres se "importan" con usar namespace std
y usar System
. Y de nuevo, incluso si esto es cierto, este argumento se aplica sólo cuando se mira a los espacios de nombres estándar. Los tuyos propios pueden diseñarse con la granularidad que desees, tanto en C# como en C++.
¿Hay más argumentos? Me interesan especialmente los hechos reales (si los hay) y no tanto las opiniones.
¿Por qué no se considera una mala práctica el "uso del sistema"?
"usar System;" no es **universalmente no se considera una mala práctica. Ver por ejemplo: ¿Por qué no usar la directiva 'using' en C#?
Pero puede ser cierto que no se considera tan mal como usar el espacio de nombres std
. Probablemente porque:
C# no tiene archivos de cabecera. Es poco común "incluir" un archivo fuente de C# en otro usando un preprocesador.
El espacio de nombres std
es casi plano, es decir, casi todas las funciones, tipos y variables de la biblioteca estándar están en él (hay algunas excepciones como el subespacio de nombres del sistema de archivos). Contiene un número muy, muy alto de identificadores. A mi entender, System
contiene muchos menos nombres, y en cambio tiene más subespacios de nombres.
En C#, no hay funciones ni variables globales. Por lo tanto, el número de identificadores globales es normalmente bastante pequeño en contraste con C++ que sí los tiene: Además, es típico utilizar bibliotecas de C (a menudo indirectamente) que no tienen espacios de nombres, y por lo tanto colocan todos sus nombres en el espacio de nombres global.
Hasta donde yo sé, C# no tiene búsqueda dependiente de argumentos. ADL en conjunción con la ocultación de nombres, la sobrecarga, etc. puede producir casos en los que algunos programas no se ven afectados por un conflicto de nombres, mientras que otros se ven sutilmente afectados, y la captura de todos los casos de esquina no es factible con las pruebas.
Debido a estas diferencias, "using System;" tiene una menor probabilidad de conflicto de nombres que using namespace std
.
Además, el espacio de nombres "importar" es, en cierto modo, una convención que se autoperpetúa: Si es convencional importar un espacio de nombres estándar, entonces los programadores convencionalmente intentarán evitar elegir nombres de ese espacio de nombres para sus propios identificadores, lo que ayuda a reducir los problemas de dicha convención.
Si dicha importación se considera una mala práctica, entonces los programadores serán menos propensos a intentar siquiera evitar los conflictos con los espacios de nombres importados. De este modo, las convenciones tienden a polarizarse a favor o en contra de la práctica, incluso si el peso de los argumentos entre las opciones era originalmente sutil.
Sin embargo, a pesar de sus diferencias, el uso de directivas en C# y C++ sirven para el mismo propósito, que es sólo tener que escribir SomeType todo el tiempo, en lugar del mucho más largo Some.Namespace.SomeType (en C++ con :: en lugar de .). Y con este mismo propósito, también me parece el peligro: las colisiones de nombres.
Sí, pero no exportar ese peligro (léase: obligar a otros a lidiar con él), por:
Ahora, entiendo que el uso de directivas en C# y C++ no son exactamente lo mismo. También, entiendo que una de las cosas más desagradables que puedes hacer con el uso de namespace en C++, es decir, ponerlo en un archivo de cabecera, no tiene equivalente en C# debido a la falta de un concepto de archivos de cabecera y #include.
Así que es una cosa bastante diferente.
Además, C++ no está "diseñado" para ser desarrollado en un IDE de la misma manera que C#. C# se escribe básicamente siempre en Visual Studio con su Intellisense y demás. Está diseñado para ser usado de esa manera, por la gente que lo creó. Independientemente de la cantidad de gente que utiliza un IDE para desarrollar en C++, no está diseñado con ese caso de uso como una preocupación abrumadora.
Los espacios de nombres parecen ser mucho más "fino granular" en C# que en C++.
Sí, eso también. usar namespace std
y usar System.Collection.Generic
son incomparables.
Así que no los compares.