Namespaces in C#
Namespaces organize related types and help prevent naming conflicts. A namespace can contain classes, structs, interfaces, enums, delegates, and other namespaces.
The traditional namespace declaration
Before C# 10, namespaces were commonly declared with braces. This is called a block-scoped namespace:
namespace MyApp.Models
{
public class Customer
{
public string Name { get; set; } = string.Empty;
}
}
All types in the namespace must be placed inside the braces. If a file contains several namespaces, each one gets its own block.
The new file-scoped declaration
C# 10 introduced file-scoped namespaces. The namespace is followed by a semicolon, and everything else in the file belongs to that namespace:
namespace MyApp.Models;
public class Customer
{
public string Name { get; set; } = string.Empty;
}
This syntax removes one level of indentation and makes files with a single namespace easier to scan. A file-scoped namespace must appear before the type declarations in the file, and a file cannot contain both a file-scoped namespace and a block-scoped namespace.
Nested namespaces
With the traditional syntax, nested namespaces are written as nested blocks:
namespace MyApp
{
namespace Services
{
public class EmailService
{
}
}
}
The same namespace can be written more clearly using a dotted name:
namespace MyApp.Services;
public class EmailService
{
}
Using types from another namespace
The using directive lets a file refer to types without writing their fully qualified names:
using MyApp.Models;
namespace MyApp.Services;
public class CustomerService
{
public Customer CreateCustomer(string name) => new() { Name = name };
}
Without a using directive, the type can be referenced by its full namespace name:
namespace MyApp.Services;
public class CustomerService
{
public MyApp.Models.Customer CreateCustomer(string name) =>
new() { Name = name };
}