Edit

Namespaces and using directives

Tip

New to developing software? Start with the Get started tutorials first. They introduce namespaces and using directives as you write your first programs.

Experienced in another language? Namespaces in C# work similarly to packages in Java or modules in Python. Skim ahead to the syntax you need.

Namespace declarations and using directives are related language features. A namespace declaration puts your types into an organized structure. A namespace groups related types together and prevents naming collisions. A using directive lets your program consume those types by their simple names. You don't have to spell out the full namespace path at every use.

You've already used namespaces in every C# program you've written. Every .NET type belongs to a namespace, and every using directive at the top of a file references one. For example, Console and Math belong to the System namespace, so their fully qualified names are System.Console and System.Math. Collection types like List<T> and Dictionary<TKey, TValue> belong to System.Collections.Generic. A single using directive for any of these namespaces lets you refer to all its types by their simple names. You write List<T> instead of System.Collections.Generic.List<T> everywhere you use it.

This article provides more background on how namespaces and using directives work, and shows examples of patterns you've already encountered in .NET libraries.

A namespace contains types. Every .NET type belongs to a namespace. For example, consider System.Threading.Tasks.Task: the type Task belongs to the System.Threading.Tasks namespace.

It's good practice to group related or similar types in the same namespace, and that's what .NET does with the types it provides. The System.Collections.Generic namespace contains collection-related types and the System.IO namespace contains types related reading and writing files, directories, and data. The System namespace contains fundamental types like Math, DateTime, and Console.

The following example shows how namespaces work together with using directives in a typical C# file:

using System;
using System.Globalization;

namespace MyApp.Services;

class Greeter
{
    public string Greet(string name)
    {
        var culture = CultureInfo.CurrentCulture;
        return $"Hello, {name}! Culture: {culture.Name}";
    }
}

In the preceding sample, the using directive means you can use the System.Globalization.CultureInfo by the name CultureInfo without specifying the full name of System.Globalization.CultureInfo. The namespace directive declares that the Greeter class is part of the MyApp.Services namespace. Its fully qualified name is MyApp.Services.Greeter.

Namespace declarations

A namespace declaration assigns your types to a named group. Every type you write should belong to a namespace. The namespace name typically mirrors the folder structure of your project. For example, types in a Services/Payments folder often belong to the MyApp.Services.Payments namespace.

Namespaces use the . operator to express hierarchy, such as System.Collections.Generic. Namespace names must be valid C# identifier names.

File-scoped namespaces

Use the file-scoped syntax when all types in a file belong to the same namespace. Add a semicolon after the namespace declaration, and it applies to the entire file. You don't need extra braces or indentation:

namespace MyApp.Models;

class Customer
{
    public required string Name { get; init; }
    public string? Email { get; init; }

    public override string ToString() => $"{Name} ({Email ?? "no email"})";
}

File-scoped namespaces reduce nesting and make files easier to read. You can only have one file-scoped namespace declaration per file.

Tip

Use file-scoped namespaces in new code. Most .NET templates and code analyzers recommend this style.

Block-scoped namespaces

Use block-scoped syntax when you need to declare more than one namespace in the same file. This style adds an extra level of indentation.

Important

It's rare to declare more than one namespace in the same file. The more common scenario is to use file-scoped namespaces.

The following snippet is an example of a block-scoped namespace:

namespace MyApp.Models
{
    class Product
    {
        public required string Name { get; init; }
        public decimal Price { get; init; }

        public override string ToString() => $"{Name}: {Price:C}";
    }
}

Using directives

Without a using directive, you must refer to every type by its fully qualified name, the complete namespace path plus the type name. This style is verbose, repetitive, and harder to read, especially when a file uses many types from the same namespace:

static void ShowFullyQualified()
{
    // Without a using directive, use the fully qualified name:
    System.Console.WriteLine("Hello from fully qualified name!");
}

A using directive at the top of a file imports a namespace so you can use its types by their simple names. The following snippet shows the shorter type usage after that import, which keeps references throughout the file shorter and easier to read:

static void ShowShortName()
{
    // With 'using System;' (or implicit usings enabled), use the short name:
    Console.WriteLine("Hello from short name!");
}

For more information, see the using directive.

Global using directives

A using directive only applies to the file it appears in. Instead of repeating the same using directives in every file, use global using directives, which let you declare them once for your entire project. Place them in any file. Many teams create a dedicated GlobalUsings.cs file:

global using System.Text;
global using System.Text.Json;

After declaring a global using, every file in the project can refer to types from that namespace by their simple names without an additional using directive. Global usings remove repetition across files, shrink the using block at the top of each file, and centralize namespace policy for the project.

Implicit usings

For the most common namespaces, you don't have to write any using directives at all. The .NET SDK automatically generates global using directives based on your project type. Enable implicit usings by setting <ImplicitUsings>enable</ImplicitUsings> in your project file. For example, a console app project automatically imports System, System.Collections.Generic, System.IO, System.Linq, System.Threading, and System.Threading.Tasks. New projects that you create with dotnet new enable ImplicitUsings by default. New files start clean, with no boilerplate using directives for everyday types like Console, List<T>, or Task.

For more information, see Implicit using directives.

Note

The other code samples in this article, and most samples throughout the .NET docs, assume that implicit usings (or the equivalent global usings for the project type) are enabled. That's why you don't see using System; and similar directives at the top of each snippet, even though the code uses types like Console or List<T> by their simple names.

Static using directives

A static using directive imports the static members of a type so you can call them without the type name prefix:

using static System.Math;

namespace MyApp.Utilities;

class CircleCalculator
{
    public static double CalculateArea(double radius) => PI * Pow(radius, 2);

    public static double CalculateCircumference(double radius) => 2 * PI * radius;
}

Static usings work well for utility classes like Math and Console that you call frequently.

Type and namespace aliases

A using alias creates a shorthand name for a type or namespace. Aliases are useful for long generic types, resolving naming conflicts, and improving readability:

using CustomerList = System.Collections.Generic.List<MyApp.Models.Customer>;

namespace MyApp.Services;

class CustomerService
{
    public CustomerList GetTopCustomers()
    {
        CustomerList customers = [new() { Name = "Alice" }, new() { Name = "Bob" }];
        return customers;
    }
}

Starting with C# 12, you can alias any type, including tuples and pointer types:

using Point = (double X, double Y);

namespace MyApp.Geometry;

class Shape
{
    public static double Distance(Point a, Point b)
    {
        var dx = a.X - b.X;
        var dy = a.Y - b.Y;
        return Math.Sqrt(dx * dx + dy * dy);
    }
}

For more advanced scenarios where two assemblies define the same fully qualified type name, use extern alias to disambiguate between them.