Clash of the Titans: using inside or outside namespace in C#
\n\nIf you've ever written in C#, you've surely seen this debate in comments or on Stack Overflow. Some developers stubbornly place using inside namespace, others — outside. And each is convinced their approach is the only correct one. But who is right? And most importantly — does it affect the performance of your code?
Let's settle this question once and for all, look under the hood of the compiler, and find out what actually happens to your using directives. Spoiler: the answer will surprise you.
What exactly are using directives and why are they needed?
\n\nBefore diving into the details, let's recall the basics. using directives are your pass to the world of other namespaces. Without them, you would have to write fully qualified names every time:
System.Console.WriteLine("Hello, world!");\nSystem.Collections.Generic.List<int> numbers = new System.Collections.Generic.List<int>();\n\nAgreed, it looks terrible. using directives make the code cleaner and more readable:
using System;\nusing System.Collections.Generic;\n\nConsole.WriteLine("Hello, world!");\nList<int> numbers = new List<int>();\n\nBut where to place them — that's the question that has plagued generations of C# developers.
\n\nTwo camps: outside vs inside
\n\nHere's what the two approaches look like:
\n\nOption 1: using outside 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 inside 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\nAt first glance, the only difference is indentation. But the community has split into two irreconcilable camps. Let's examine the arguments of each.
\n\nArgument #1: Performance and compilation
\n\nThe most common question: does the placement of using affect performance? The short answer: NO. And here's why.
using directives are purely syntactic sugar for the compiler. They exist only during the compilation phase. When your code is transformed into IL (Intermediate Language), no trace of the using directives remains. The compiler simply uses them to resolve type names and then discards them.
Let's prove this in practice. Consider this code:
\n\n// File: 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\nAfter compilation into IL code, you will see something like this (greatly simplified):
\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 // Creating List<int>\n newobj instance void class [System.Runtime]System.Collections.Generic.List`1<int32>::.ctor()\n stloc.0\n \n // Calling 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\nNotice: in the IL code, fully qualified names are used (System.Collections.Generic.List`1,