Pourquoi «utilise le système;» pas considéré comme une mauvaise pratique?

47

J'ai une formation en C ++ et je comprends parfaitement et suis d'accord avec les réponses à cette question: pourquoi «utiliser namespace std;» considéré comme une mauvaise pratique?

Je suis donc étonné que, ayant une certaine expérience avec C # maintenant, je vois exactement le contraire: il using Some.Namespace;est littéralement utilisé partout. Chaque fois que vous commencez à utiliser un type, vous ajoutez d'abord une directive using pour son espace de noms (si ce n'est déjà fait). Je ne me souviens pas avoir vu un .csfichier qui n'a pas commencé using System; using System.Collections.Generic; using X.Y.Z; etc.... En fait, si vous ajoutez un nouveau fichier via l'assistant Visual Studio, il y ajoute automatiquement des directives d'utilisation, même si vous n'en avez pas du tout besoin. Ainsi, alors que dans la communauté C ++, vous êtes essentiellement lynché, C # encourage même à le faire. C'est du moins ainsi que cela m'apparaît.

Maintenant, je comprends que l'utilisation de directives en C # et C ++ n'est pas exactement la même chose. En outre, je comprends que l'une des choses les plus méchantes que vous puissiez faire using namespaceen C ++, à savoir le placer dans un fichier d'en-tête, n'a pas d'équivalent équivalent en C # en raison de l'absence d'un concept de fichiers d'en-tête et #include.

Cependant, malgré leurs différences, l'utilisation des directives en C # et C ++ sert le même but, qui n'a qu'à taper SomeTypetout le temps, plutôt que beaucoup plus longtemps Some.Namespace.SomeType(en C ++ avec ::au lieu de .). Et dans ce même but, le danger me semble également le même: nommer les collisions.

Dans le meilleur des cas, cela entraîne une erreur de compilation, vous n'avez donc "qu'à" le corriger. Dans le pire des cas, il compile toujours et le code fait silencieusement des choses différentes de ce que vous aviez l'intention de faire. Ma question est donc la suivante: pourquoi (apparemment) utilise-t-on des directives considérées comme si inégalement mauvaises en C # et C ++?

Quelques idées de réponse que j'ai (aucune de ces réponses ne me satisfait vraiment, cependant):

  • Les espaces de noms ont tendance à être beaucoup plus longs et beaucoup plus imbriqués en C # qu'en C ++ ( stdvs. System.Collection.Generic). Ainsi, il y a plus de désir et plus de gain à débruiter le code de cette façon. Mais même si cela est vrai, cet argument ne s'applique que lorsque nous regardons les espaces de noms standard. Les noms personnalisés peuvent avoir n'importe quel nom court que vous aimez, à la fois en C # et C ++.

  • Les espaces de noms semblent être beaucoup plus "fins" en C # qu'en C ++. À titre d'exemple, en C ++ toute la bibliothèque standard est contenue dans std(plus quelques petits espaces de noms imbriqués comme chrono) tout en C # vous System.IO, System.Threading, System.Textetc. Ainsi, le risque d'avoir des collisions de nommage est plus petite. Cependant, ce n'est qu'un sentiment d'intestin. Je n'ai pas vraiment compté le nombre de noms que vous "importez" avec using namespace stdet using System. Et encore une fois, même si cela est vrai, cet argument ne s'applique que lorsque l'on regarde les espaces de noms standard. Les vôtres peuvent être conçus aussi fins que vous le souhaitez, en C # et en C ++.

Y a-t-il d'autres arguments? Je m'intéresse particulièrement aux faits réels (s'il y en a) et pas tellement aux opinions.

sebrockm
la source
2
@Timo L'OP ne pose pas explicitement de question sur la pollution des en-têtes.
Konrad Rudolph
1
J'ai supposé que c'était parce qu'il n'y avait pas de concurrence pour l'espace de noms global au même degré qu'en C ++ (principalement en raison de la bibliothèque standard C). Mais j'attends les réponses de ceux qui connaissent le mieux.
Wyck
2
@ThomasWeller En C ++ c'est évident. En C #, considérez une méthode d'extensions avec Ext(this T t, long l)qui est appelée via t.Ext(0). Si vous ajoutez ensuite un autre espace de noms contenant une méthode d'extension Ext(this T t, int i), celui-ci sera appelé à la place. Mais je ne suis pas (encore) un expert en C #.
sebrockm
2
@Franck même si je vous ai accordé ce point, alors le même argument s'applique au C ++, poussant davantage ma question de ne pas voir la différence entre C ++ et C #
sebrockm
3
@Franck C ++ vous enverra une erreur de compilation en cas d'ambiguïté. Ainsi que C #.
Timo

Réponses:

28

Pourquoi «utilise le système;» pas considéré comme une mauvaise pratique?

"using System;" n'est pas universellement considéré comme une mauvaise pratique. Voir par exemple: Pourquoi n'utilisez-vous pas la directive 'using' en C #?

Mais il peut être vrai que ce n'est pas considéré comme aussi mauvais que using namespace std. Probablement parce que:

  1. C # n'a pas de fichiers d'en-tête. Il est rare "d'inclure" un fichier source C # dans un autre à l'aide d'un pré-processeur.

  2. stdl'espace de noms est presque plat, c'est-à-dire que presque toutes les fonctions, types et variables de bibliothèque standard s'y trouvent (il y a quelques exceptions comme le sous-espace de noms du système de fichiers). Il contient un nombre très, très élevé d'identifiants. À ma connaissance, Systemcontient beaucoup moins de noms et contient plutôt plus de sous-espaces de noms.

  3. En C #, il n'y a pas de fonctions ou variables globales. En tant que tel, le nombre d'identificateurs globaux est généralement assez petit contrairement à C ++ qui en a: En outre, il est typique d'utiliser des bibliothèques C (souvent indirectement) qui n'ont pas d'espaces de noms, et donc de placer tous leurs noms dans le global espace de noms.

  4. Pour autant que je sache, C # n'a pas de recherche dépendante des arguments. ADL en conjonction avec le masquage de nom, la surcharge, etc. peut produire des cas où certains programmes ne sont pas affectés par un conflit de nom, tandis que d'autres sont subtilement affectés, et la capture de tous les cas de coin n'est pas possible avec les tests.

En raison de ces différences, «utiliser System;» a moins de chances de conflit de noms que using namespace std.


De plus, "l'importation" d'espace de noms est en quelque sorte une convention qui se perpétue: s'il est conventionnel d'importer un espace de noms standard, les programmeurs essaieront généralement d'éviter de choisir des noms de cet espace de noms pour leurs propres identificateurs, ce qui contribue à réduire les problèmes avec une telle convention.

Si une telle importation est considérée comme une mauvaise pratique, les programmeurs seront même moins susceptibles de tenter d'éviter de tels conflits avec les espaces de noms importés. En tant que telles, les conventions ont tendance à se polariser pour ou contre la pratique, même si les poids des arguments entre les choix étaient à l'origine subtils.

eerorika
la source
3
Cela ne prend en compte que les inconvénients potentiels de l'ouverture des espaces de noms. C'est un début, mais je pense que nous devons également considérer les avantages: dans le cas de C ++, dans la plupart des cas, il enregistre cinq caractères ( std::). En C #, c'est beaucoup plus ( System.n'a «que» 7 caractères, mais d'autres espaces de noms imbriqués ont beaucoup plus de caractères, et les écrire partout rendrait le code complètement illisible).
Konrad Rudolph
N'est-il pas également le cas que la résolution de surcharge C # est plus gentille que celle en C ++ et beaucoup d'ambiguïté est tirée via les erreurs du compilateur? (En aucun cas une critique de votre réponse qui semble autoritaire.)
Bathsheba
3
@KonradRudolph Si les inconvénients étaient considérés comme importants, et la quantité de frappe également (par rapport à la quantité de frappe std::), ne serait-ce pas un style typique d'utiliser à la using Sys = System;place le namespace polluant non-alias using?
eerorika
2
@Bathsheba concernant "faisant autorité", je voudrais nier que je sais très peu de choses sur C #, et ma réponse est basée sur la connaissance de C ++, et quelques recherches google sur C #. Donc, j'apprécierais si quelqu'un vérifie les parties C # :)
eerorika
2
Concernant la partie ADL: C # a des méthodes d'extension. C'est une conception différente d'ADL, mais ils partagent les mêmes problèmes concernant les conflits de noms.
Timo
-2

Cependant, malgré leurs différences, l'utilisation de directives en C # et C ++ sert le même but, qui n'a qu'à taper SomeType tout le temps, plutôt que le beaucoup plus long Some.Namespace.SomeType (en C ++ avec :: au lieu de.). Et dans ce même but, le danger me semble aussi: nommer les collisions.

Oui, mais vous n'avez pas exporté ce danger (lire: forcer les autres à y faire face), à ​​cause de:

Maintenant, je comprends que l'utilisation de directives en C # et C ++ n'est pas exactement la même chose. De plus, je comprends que l'une des choses les plus méchantes que vous puissiez faire avec l'utilisation de l'espace de noms en C ++, à savoir le placer dans un fichier d'en-tête, n'a pas d'équivalent en C # en raison de l'absence d'un concept de fichiers d'en-tête et #include.

C'est donc plutôt une catégorie de choses différente.

De plus, C ++ n'est pas "conçu" pour être développé dans un IDE de la même manière que C #. C # est fondamentalement toujours écrit dans Visual Studio avec son Intellisense et ainsi de suite. Il est conçu pour être utilisé de cette façon par les personnes qui l'ont créé. Quel que soit le nombre de personnes qui utilisent un IDE pour développer en C ++, il n'est pas conçu avec ce cas d'utilisation comme une préoccupation majeure.

Les espaces de noms semblent être beaucoup plus "fins" en C # qu'en C ++.

Oui, ça aussi. using namespace stdet using System.Collection.Genericsont incomparables.

Alors ne les comparez pas!

Astéroïdes avec des ailes
la source
2
Cela ne répond pas à la préoccupation d'OP, qui ne concerne explicitement pas l' ouverture d'espaces de noms dans les en-têtes, mais dans les fichiers d'implémentation .
Konrad Rudolph
2
@KonradRudolph Le conseil à éviter using namespace stden C ++ concerne principalement les fichiers d'en-tête. La réponse est que cela ne s'applique pas en C #.
Asteroids With Wings
8
@AsteroidsWithWings les conseils à éviter ne using namespace stdsont certainement pas principalement des en-têtes. Son utilisation dans les en-têtes est dangereuse. Son utilisation dans vos implémentations est déconseillée.
Tommy Andersen
1
Le conseil à éviter using namespace ...en c ++ est d'éviter la collision de noms, la usingdirective en C # introduit également la possibilité de nommer la collision, alors pourquoi ne pas l'éviter? Même si leur mise en œuvre diffère.
Tommy Andersen
@TommyAndersen, est-il difficile de résoudre un tel conflit s'il se produit? Ça prend une seconde. Étant donné que les usingdéclarations C # sont par fichier qui définit un type / classe unique et que le type a normalement à voir avec un ensemble relativement étroit de concepts de domaine d'application (idéalement, principe de responsabilité unique), la probabilité de tels conflits d'espace de noms est extrêmement faible. Mais quand cela arrive est facilement réparable. Les outils de développement .NET / IDE courants vous aident beaucoup avec cela. Considérez l'ensemble de l'écosystème de développement conçu pour vous rendre plus productif en combinant le meilleur des multiples activités de développement
AKornich