¿Por qué está "usando el sistema"? no se considera mala práctica?

47

Tengo experiencia en C ++ y entiendo completamente y estoy de acuerdo con las respuestas a esta pregunta: ¿Por qué está "usando el espacio de nombres std;" considerado una mala práctica?

Así que me sorprende que, teniendo algo de experiencia con C # ahora, veo exactamente lo contrario: using Some.Namespace;literalmente se usa en todas partes. Cada vez que comienza a usar un tipo, primero agrega una directiva de uso para su espacio de nombres (si aún no está allí). No recuerdo haber visto un .csarchivo que no comenzó using System; using System.Collections.Generic; using X.Y.Z; etc.... De hecho, si agrega un nuevo archivo a través del asistente de Visual Studio, automáticamente agrega algunos usando directivas allí, aunque puede que no los necesite en absoluto. Entonces, mientras que en la comunidad de C ++ te linchan básicamente, C # incluso anima a hacer esto. Al menos así es como me parece.

Ahora, entiendo que usar directivas en C # y C ++ no es exactamente lo mismo. Además, entiendo que una de las cosas más desagradables que puede hacer using namespaceen C ++, es decir, ponerlo en un archivo de encabezado, no tiene una contraparte equivalente desagradable en C # debido a la falta de un concepto de archivos de encabezado y #include.

Sin embargo, a pesar de sus diferencias, el uso de directivas en C # y C ++ tiene el mismo propósito, que solo tiene que escribir SomeTypetodo el tiempo, en lugar de hacerlo por mucho más tiempo Some.Namespace.SomeType(en C ++ con en ::lugar de .). Y con este mismo propósito, también el peligro parece ser el mismo para mí: nombrar colisiones.

En el mejor de los casos, esto da como resultado un error de compilación, por lo que "solo" tiene que solucionarlo. En el peor de los casos, aún se compila y el código en silencio hace cosas diferentes de lo que pretendía que hiciera. Entonces mi pregunta es: ¿por qué (aparentemente) están usando directivas consideradas tan desigualmente malas en C # y C ++?

Algunas ideas de una respuesta que tengo (ninguna de estas realmente me satisface):

  • Los espacios de nombres tienden a ser mucho más largos y mucho más anidados en C # que en C ++ ( stdvs. System.Collection.Generic). Entonces, hay más ganas y más ganancias al eliminar el ruido de este modo. Pero incluso si esto es cierto, este argumento solo se aplica cuando miramos los espacios de nombres estándar. Los personalizados pueden tener cualquier nombre corto que desee, tanto en C # como en C ++.

  • Los espacios de nombres parecen ser mucho más "granulares finos" en C # que en C ++. A modo de ejemplo, en C ++ toda la biblioteca estándar está contenida en std(además de algunos pequeños espacios de nombres anidados gustaría chrono), mientras que en C # que tiene System.IO, System.Threading, System.Textetc Por lo tanto, el riesgo de que las colisiones de nombres es menor. Sin embargo, esto es solo un presentimiento. En realidad no conté cuántos nombres "importas" con using namespace stdy using System. Y nuevamente, incluso si esto es cierto, este argumento se aplica solo cuando se observan los espacios de nombres estándar. Los suyos pueden diseñarse tan bien como desee, tanto en C # como en C ++.

¿Hay más argumentos? Estoy especialmente interesado en hechos concretos reales (si los hay) y no tanto en las opiniones.

sebrockm
fuente
2
@Timo El OP explícitamente no pregunta sobre la contaminación del encabezado.
Konrad Rudolph
1
Supuse que era porque no hay competencia para el espacio de nombres global en el mismo grado que existe en C ++ (principalmente debido a la biblioteca estándar de C). Pero espero las respuestas de los que mejor conocen.
Wyck
2
@ThomasWeller En C ++ es obvio. En C # considere un método de extensiones Ext(this T t, long l)que se llama vía t.Ext(0). Si luego agrega otro espacio de nombres que contiene un método de extensión Ext(this T t, int i), se llamará a ese. Pero no soy un experto en C # (todavía).
sebrockm
2
@Franck, incluso si le concedí ese punto, entonces el mismo argumento se aplica a C ++, empujando aún más mi pregunta de no ver la diferencia entre C ++ y C #
sebrockm
3
@Franck C ++ arrojará un error de compilación en caso de ambigüedad. Además de C #.
Timo

Respuestas:

28

¿Por qué está "usando el sistema"? no se considera mala práctica?

"usando el sistema"; se no universalmente no se considera una mala práctica. Vea, por ejemplo: ¿Por qué no usaría la directiva 'usar' en C #?

Pero puede ser cierto que no se considera tan malo como using namespace std. Probablemente porque:

  1. C # no tiene archivos de encabezado. Es poco común "incluir" un archivo fuente de C # en otro utilizando un preprocesador.

  2. stdel espacio de nombres es casi plano, es decir, casi todas las funciones, tipos y variables estándar de la biblioteca están en él (hay algunas excepciones, como el subespacio del sistema de archivos). Contiene un número muy, muy alto de identificadores. Según tengo entendido, Systemcontiene muchos menos nombres y, en cambio, tiene más subespacios de nombres.

  3. En C #, no hay funciones o variables globales. Como tal, el número de identificadores globales suele ser bastante pequeño en contraste con C ++ que tiene esos: Además, es típico usar bibliotecas C (a menudo indirectamente) que no tienen espacios de nombres y, por lo tanto, colocan todos sus nombres en el global espacio de nombres

  4. Hasta donde yo sé, C # no tiene búsqueda dependiente de argumentos. ADL junto 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 afectados sutilmente, y no es factible detectar todos los casos de esquina con las pruebas.

Debido a estas diferencias, "usar el sistema"; tiene menos posibilidades de conflicto de nombres que using namespace std.


Además, la "importación" del espacio de nombres es, en cierto modo, una convención que se perpetúa a sí misma: si es convencional importar un espacio de nombres estándar, entonces los programadores intentarán evitar elegir nombres de ese espacio de nombres para sus propios identificadores, lo que ayuda a reducir los problemas con tal convención.

Si dicha importación se considera una mala práctica, entonces será menos probable que los programadores intenten evitar conflictos con espacios de nombres importados. Como tal, las convenciones tienden a polarizarse a favor o en contra de la práctica, incluso si los pesos de los argumentos entre las elecciones fueron originalmente sutiles.

eerorika
fuente
3
Esto considera solo los posibles inconvenientes de abrir espacios de nombres. Es un comienzo, pero creo que también debemos tener en cuenta las ventajas: en el caso de C ++, en la mayoría de los casos está ahorrando cinco caracteres ( std::). En C #, es sustancialmente más ( System.tiene "solo" 7 caracteres, pero otros espacios de nombres anidados tienen muchos más caracteres, y escribirlos en todas partes haría que el código sea completamente ilegible).
Konrad Rudolph
¿No es también el caso de que la resolución de sobrecarga de C # es más amable que la de C ++ y se genera mucha ambigüedad a través de errores del compilador? (De ninguna manera es una crítica de su respuesta que parece autorizada.)
Betsabé
3
@KonradRudolph Si los inconvenientes se consideraran significativos, y la cantidad de tipeo de la misma manera (en comparación con la cantidad de tipeo std::), ¿no sería un estilo típico usar using Sys = System;en su lugar el no alias contaminante del espacio de nombres using?
Eerorika
2
@Bathsheba con respecto a "autoridad", me gustaría negar que sé muy poco acerca de C #, y mi respuesta se basa en el conocimiento de C ++, y algunas búsquedas de Google sobre C #. Entonces, agradecería que alguien verifique las partes de C # :)
eerorika
2
En cuanto a la parte ADL: C # tiene métodos de extensión. Es un diseño diferente al ADL, pero comparten los mismos problemas con respecto a los conflictos de nombres.
Timo
-2

Sin embargo, a pesar de sus diferencias, el uso de directivas en C # y C ++ tiene el mismo propósito, que solo es tener que escribir SomeType todo el tiempo, en lugar del más largo Some.Namespace.SomeType (en C ++ con :: en lugar de). Y con este mismo propósito, también el peligro parece ser para mí: nombrar colisiones.

Sí, pero no exportó ese peligro (léase: obligar a otros a lidiar con él) debido a:

Ahora, entiendo que usar directivas en C # y C ++ no es exactamente lo mismo. Además, entiendo que una de las cosas más desagradables que puede hacer con el uso del espacio de nombres en C ++, es decir, ponerlo en un archivo de encabezado, no tiene equivalente en C # debido a la falta de un concepto de archivos de encabezado e #include.

Entonces es más bien una categoría diferente de cosas.

Además, C ++ no está "diseñado" para desarrollarse en un IDE de la misma manera que C #. C # básicamente siempre se escribe en Visual Studio con su Intellisense y demás. Está diseñado para ser utilizado de esa manera, por las personas que lo crearon. Independientemente de cuántas personas usan 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 "granulares finos" en C # que en C ++.

Sí eso también. using namespace stdy using System.Collection.Genericson incomparables

¡Así que no los compares!

Asteroides con alas
fuente
2
Esto no responde a la preocupación de OP, que explícitamente no se trata de abrir espacios de nombres en encabezados, sino en archivos de implementación .
Konrad Rudolph
2
@KonradRudolph El consejo para evitar using namespace stden C ++ es principalmente sobre archivos de encabezado. La respuesta es que esto no se aplica en C #.
Asteroides con alas
8
@AsteroidsWithWings el consejo para evitar using namespace stdciertamente no se trata principalmente de encabezados. Usarlo en encabezados es peligroso. Se desaconseja su uso en sus implementaciones.
Tommy Andersen
1
El consejo para evitar using namespace ...en c ++ es evitar la colisión de nombres, la usingdirectiva en C # introduce la posibilidad de colisión de nombres también, entonces ¿por qué no evitarla? A pesar de que la implementación difiere.
Tommy Andersen
@TommyAndersen, ¿qué tan difícil es resolver tal conflicto si sucede? Toma un segundo Dado que las usingdeclaraciones de C # son por archivo que define un tipo / clase único y el tipo normalmente tiene que ver con un conjunto relativamente limitado de conceptos de dominio de aplicación (idealmente, principio de responsabilidad única), la probabilidad de tales conflictos de espacio de nombres es extremadamente baja. Pero cuando suceden son fácilmente reparables. Las herramientas de desarrollo comunes de .NET / IDE lo ayudan mucho con eso. Considere todo el ecosistema de desarrollo que está diseñado para hacerlo más productivo combinando lo mejor de múltiples actividades de desarrollo
AKornich