Guerre des mondes : using à l'intérieur ou à l'extérieur du namespace en C#
\n\nSi vous avez déjà écrit en C#, vous avez sûrement vu ce débat dans les commentaires ou sur Stack Overflow. Certains développeurs écrivent obstinément using à l'intérieur du namespace, d'autres à l'extérieur. Et chacun est convaincu que son approche est la seule correcte. Mais qui a raison ? Et surtout, cela affecte-t-il les performances de votre code ?
Examinons cette question une fois pour toutes, regardons sous le capot du compilateur et découvrons ce qui arrive réellement à vos directives using. Spoiler : la réponse va vous surprendre.
Que sont les directives using et à quoi servent-elles ?
\n\nAvant de plonger dans les détails, rappelons les bases. Les directives using sont votre passeport vers le monde des espaces de noms externes. Sans elles, vous devriez écrire à chaque fois les noms complets qualifiés :
System.Console.WriteLine("Bonjour le monde !");\nSystem.Collections.Generic.List<int> numbers = new System.Collections.Generic.List<int>();\n\nD'accord, cela semble horrible. Les directives using rendent le code plus propre et plus lisible :
using System;\nusing System.Collections.Generic;\n\nConsole.WriteLine("Bonjour le monde !");\nList<int> numbers = new List<int>();\n\nMais où les placer ? C'est une question qui tourmente des générations de développeurs C#.
\n\nDeux camps : à l'extérieur vs à l'intérieur
\n\nVoici à quoi ressemblent les deux approches :
\n\nOption 1 : using à l'extérieur du namespace
\n\nusing System;\nusing System.Collections.Generic;\n\nnamespace MyApp\n{\n class Program\n {\n static void Main()\n {\n List<int> list = new List<int>();\n }\n }\n}\n\nOption 2 : using à l'intérieur du namespace
\n\nnamespace MyApp\n{\n using System;\n using System.Collections.Generic;\n\n class Program\n {\n static void Main()\n {\n List<int> list = new List<int>();\n }\n }\n}\n\nÀ première vue, la différence réside uniquement dans l'indentation. Mais la communauté s'est divisée en deux camps irréconciliables. Analysons les arguments de chacun.
\n\nArgument n°1 : Performances et compilation
\n\nLa question la plus fréquente : l'emplacement du using affecte-t-il les performances ? Réponse courte : NON. Et voici pourquoi.
Les directives using sont purement du sucre syntaxique pour le compilateur. Elles n'existent que pendant la phase de compilation. Lorsque votre code est transformé en IL (Intermediate Language), il ne reste aucune trace des directives using. Le compilateur les utilise simplement pour résoudre les noms de types, puis les jette.
Prouvons-le en pratique. Considérons ce code :
\n\n// Fichier : Program.cs\nusing System;\nusing System.Collections.Generic;\n\nnamespace MyApp\n{\n class Program\n {\n static void Main()\n {\n List<int> list = new List<int>();\n Console.WriteLine(list.Count);\n }\n }\n}\n\nAprès compilation en code IL, vous verrez approximativement ceci (très simplifié) :
\n\n.method private hidebysig static void Main() cil managed\n{\n .entrypoint\n .maxstack 1\n .locals init (\n [0] class [System.Runtime]System.Collections.Generic.List`1<int32> list\n )\n \n // Création de List<int>\n newobj instance void class [System.Runtime]System.Collections.Generic.List`1<int32>::.ctor()\n stloc.0\n \n // Appel de Console.WriteLine\n ldloc.0\n callvirt instance int32 class [System.Runtime]System.Collections.Generic.List`1<int32>::get_Count()\n call void [System.Console]System.Console::WriteLine(int32)\n \n ret\n}\n\nRemarquez : dans le code IL, des noms complets qualifiés sont utilisés (System.Collections.Generic.List`1,