Every type in .NET has a full name made of a namespace and the type name: System.Console, System.Collections.Generic.List<T>, System.Text.StringBuilder. Namespaces group related types and keep names from clashing, so your own Order or Timer class can coexist with ones from libraries. The using directive at the top of a file imports a namespace so you can use the short names.
Output:
Cart: tea, honey
1
A using directive only affects names at compile time. It does not load a library or add code to the program; which libraries are available is decided by the project's references and NuGet packages. If the compiler reports that a type or namespace "could not be found (are you missing a using directive or an assembly reference?)", error CS0246, either the using line is missing or the package is not referenced.
Declaring your own namespaces
Put types inside a namespace block. Namespaces can be nested, written with dots, and the same namespace can be spread across many files.
Output:
120.00 via DHL
Shop.Billing.Invoice
namespace Shop.Billing { } is shorthand for namespace Shop { namespace Billing { } }. Code inside Shop can refer to Billing.Invoice without the Shop. prefix, because names are looked up in the enclosing namespaces first.
Conventions: start with the company or product (Contoso.Payments), then the feature or layer, and match the folder structure (Contoso.Payments/Refunds/RefundService.cs holds Contoso.Payments.Refunds). Never name a class the same as its namespace (Shop.Shop), which forces awkward qualification everywhere.
Aliases
using Name = Namespace.Type; gives a type (or a namespace) a local name. Two situations call for it: shortening a long generic type, and resolving a clash.
Output:
latte: 3.60
order 17
Aliases only apply to the file they are declared in (unless they are global, below). In C# 12 and later an alias can name any type, including tuples and arrays: using Point = (int X, int Y);.
Ambiguous references (CS0104)
When two imported namespaces contain a type with the same name, using the short name is an error. The classic case is Timer, which exists in System.Threading, System.Timers and (in desktop apps) System.Windows.Forms:
using System.Threading;
using System.Timers;
var t = new Timer(1000);
// error CS0104: 'Timer' is an ambiguous reference between
// 'System.Timers.Timer' and 'System.Threading.Timer'
Three fixes, from most to least local: write the fully qualified name (new System.Timers.Timer(1000)), add an alias that says which one you mean, or remove the directive you do not need.
Output:
250
System.Timers.Timer
System.Threading.Timer
If your own namespace defines a type called System or Console, the prefix global:: forces lookup from the root: global::System.Console.WriteLine("hi");. Generated code uses it everywhere for that reason.
using static
using static imports the static members of a single type, so they can be called without the type name. It suits code that calls the same class over and over, like Math:
Output:
Area: 28.27
Hypotenuse: 5
42
using static also works with enums (using static System.DayOfWeek; lets you write Monday) and with your own static classes. Use it where the short names stay unambiguous; WriteLine alone in a large file can leave readers wondering which writer it is.
global using and file-scoped namespaces (C# 10)
Two C# 10 features cut the boilerplate at the top of files. A global using applies to every file in the project, and is usually kept in one file such as GlobalUsings.cs:
// GlobalUsings.cs, C# 10 and later
global using System;
global using System.Collections.Generic;
global using System.Linq;
global using Money = System.Decimal;
SDK projects on .NET 6 and later can generate these for you. With <ImplicitUsings>enable</ImplicitUsings> in the .csproj (the default in new templates), a console project gets System, System.Collections.Generic, System.IO, System.Linq, System.Net.Http, System.Threading and System.Threading.Tasks; web projects get ASP.NET Core namespaces as well. That is why modern Program.cs files start straight with code.
A file-scoped namespace declares the namespace for the whole file with a semicolon instead of a block, saving one level of indentation:
// C# 10 and later
namespace Shop.Billing;
public class Invoice
{
public decimal Amount { get; set; }
}
A file can have only one file-scoped namespace, and it cannot be mixed with block namespaces in the same file. Older projects, Unity scripts and code that targets .NET Framework use the block form shown earlier.
Where using directives go, and the using statement
Using directives must come before any namespace or type declarations in the file (global usings before everything else). They can also be placed inside a namespace block, in which case they apply only there; style guides differ, and most .NET code keeps them at the top.
The keyword using has a second, unrelated job inside methods: the using statement using (var file = File.OpenRead(path)) { ... } calls Dispose on the object when the block ends, closing files and connections. It shares the keyword and nothing else. See the using statement page.
Frequently Asked Questions
What does using do in C#?
At the top of a file, using System.Text; is a directive that imports a namespace, so you can write StringBuilder instead of System.Text.StringBuilder. It adds no code and loads nothing; it only shortens names. Inside a method, using (var f = ...) is a different feature, the using statement, which disposes an object at the end of a block.
What is a namespace in C#?
A namespace is a named group of types that prevents name clashes and organizes code, such as System.Collections.Generic or MyShop.Billing. Two classes can share a name if they are in different namespaces. By convention namespaces follow the folder structure and start with the company or product name.
What is using static in C#?
using static System.Math; imports the static members of one type, so you can call Sqrt(16) and read PI without the Math. prefix. It works with any class, including your own and enums. Use it where the short names stay clear, such as math-heavy code.
How do I fix "is an ambiguous reference" in C#?
Error CS0104 means two imported namespaces both contain a type with that name, for example Timer in System.Threading and System.Timers. Write the fully qualified name (System.Timers.Timer), remove one of the using directives, or add an alias: using Timer = System.Timers.Timer;.
What is global using in C#?
global using System.Text; (C# 10) imports a namespace for every file in the project, not just the one it appears in. .NET 6 and later SDK projects generate a set of global usings automatically when <ImplicitUsings>enable</ImplicitUsings> is set, which is why new Program.cs files have no using lines.