Пространства имен и директивы using

Подсказка

Вы новичок в разработке программного обеспечения? Сначала начните с учебников для начинающих. Они вводят пространства имен и using директивы, когда вы начинаете писать свои первые программы.

Есть опыт на другом языке? Пространства имен в C# работают похожим образом, как пакеты в Java или модули в Python. Перейдите к нужному синтаксису.

Объявления пространства имен и using директивы связаны с языковыми особенностями. Объявление пространства имен структурирует ваши типы данных. Пространство имен группирует связанные типы и предотвращает столкновения именования. Директива using позволяет вашей программе использовать эти типы по их упрощенным именам. Вам не нужно указывать полный путь к пространству имен при каждом использовании.

Вы уже использовали пространства имен в каждой программе C#, которую вы написали. Каждый тип .NET принадлежит пространству имен, и каждая using директива в верхней части файла ссылается на один. Например, Console и Math принадлежат к пространству имен System, поэтому их полные имена — это System.Console и System.Math. Типы коллекций, подобные List<T> и Dictionary<TKey, TValue>, принадлежащие System.Collections.Generic. using Одна директива для любого из этих пространств имен позволяет ссылаться на все его типы по простым именам. Вы пишете List<T> вместо того, чтобы System.Collections.Generic.List<T> везде, где вы его используете.

В этой статье содержатся дополнительные сведения о работе пространств имен и using директив, а также примеры шаблонов, которые вы уже обнаружили в библиотеках .NET.

Пространство имен содержит типы. Каждый тип .NET принадлежит пространству имен. Например, рассмотрим System.Threading.Tasks.Task: тип Task принадлежит пространству System.Threading.Tasks имен.

Рекомендуется группировать связанные или аналогичные типы в одном пространстве имен, и это то, что делает .NET с указанными типами. Пространство имен System.Collections.Generic содержит типы, связанные с коллекцией, а пространство имен System.IO содержит типы, связанные с работой с чтением и записью файлов, каталогов и данных. Пространство System имен содержит основные типы, такие как Math, DateTimeи Console.

В следующем примере показано, как пространства имен работают вместе с using директивами в типичном файле C#:

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}";
    }
}

В предыдущем примере директива using означает, что вы можете использовать System.Globalization.CultureInfo по имени CultureInfo без необходимости указывать полное имя System.Globalization.CultureInfo. Директива namespace объявляет, что Greeter класс является частью MyApp.Services пространства имен. Полное имя MyApp.Services.Greeter.

Объявления пространства имен

Объявление пространства имен присваивает ваши типы к названной группе. Каждый тип, который вы записываете, должен принадлежать пространству имен. Имя пространства имен обычно отражает структуру папок проекта. Например, типы в папке Services/Payments часто принадлежат пространству имен MyApp.Services.Payments.

Пространства имен используют оператор . для выражения иерархии, например System.Collections.Generic. Имена пространств имен в C# должны быть допустимыми именами идентификаторов.

Пространства имен с областью действия файла

Используйте синтаксис с областью действия файла , если все типы в файле принадлежат одному пространству имен. После объявления пространства имен добавьте точку с запятой; это будет применяться ко всему файлу. Вам не нужны дополнительные отступы или фигурные скобки.

namespace MyApp.Models;

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

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

Пространства имен с областью действия файлов сокращают вложенные файлы и упрощают чтение файлов. В каждом файле может быть только одно пространство имен, ограниченное файлом.

Подсказка

Используйте пространства имен, ограниченные файлом, в новом коде. Большинство шаблонов .NET и анализаторов кода рекомендуют этот стиль.

Блочные пространства имен

Используйте синтаксис блочной области видимости, если необходимо объявить несколько пространств имен в одном файле. Этот стиль добавляет дополнительный уровень отступа.

Это важно

Редко объявляют несколько пространств имен в одном файле. Более распространенный сценарий — использовать пространства имен с областью действия файла .

Следующий фрагмент кода является примером блочного пространства имен:

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

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

Директивы using

Без директивы using необходимо ссылаться на каждый тип по его полностью квалифицированному имени — полному пути пространства имён и имени типа. Этот стиль является подробным, повторяющимся и трудным для чтения, особенно если файл использует множество типов из одного пространства имен:

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

Директива using в начале файла импортирует пространство имён, чтобы можно было использовать содержащиеся в нём типы, указывая только их простые имена. В следующем фрагменте кода показано использование сокращённого имени типа после такого импорта, благодаря чему обращения к нему по всему файлу становятся короче и их легче читать:

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

Дополнительные сведения см. в директивеusing.

Глобальные директивы using

Директива using применяется только к файлу, в который он отображается. Вместо того чтобы повторять те же using директивы в каждом файле, используйте глобальные директивы using , которые позволяют объявлять их один раз для всего проекта. Поместите их в любой файл. Многие команды создают выделенный GlobalUsings.cs файл:

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

После объявления глобального использования каждый файл в проекте может ссылаться на типы из этого пространства имен по простым именам без дополнительной using директивы. Глобальные директивы using устраняют повторения в разных файлах, уменьшают блок using в начале каждого файла и централизуют политику пространств имён в проекте.

Неявное использование

Для наиболее распространенных пространств имен вам не нужно писать директивы using вообще. .NET SDK автоматически создаёт глобальные директивы using в зависимости от типа проекта. Включите неявное использование, установив <ImplicitUsings>enable</ImplicitUsings> в файле проекта. Например, проект консольного приложения автоматически импортирует System, System.Collections.Generic, System.IO, System.Linq, System.Threading и System.Threading.Tasks. В новых проектах, создаваемых с помощью dotnet new, ImplicitUsings включён по умолчанию. Новые файлы создаются без лишнего, без шаблонных using директив для часто используемых типов, таких как Console, List<T> или Task.

См. раздел «Неявные директивы using» для получения дополнительной информации.

Note

Другие примеры кода в этой статье, а также большинство примеров в документации по .NET, предполагают, что неявные директивы using (или эквивалентные глобальные директивы using для этого типа проекта) включены. Именно поэтому вы не видите using System; и аналогичные директивы в верхней части каждого фрагмента кода, даже если код использует типы, подобные Console или List<T> по их простым именам.

Статические директивы using

Директива static using импортирует статические элементы типа, чтобы их можно было вызывать без префикса имени типа:

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;
}

Статические использования хорошо работают для служебных классов, таких как Math и Console, которые вы часто вызываете.

Псевдонимы типа и пространства имен

Псевдоним using создает сокращенное имя для типа или пространства имен. Псевдонимы полезны для длинных общих типов, разрешения конфликтов именования и повышения удобочитаемости.

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;
    }
}

Начиная с C# 12, можно псевдонимить любой тип, включая кортежи и типы указателей:

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);
    }
}

Для более продвинутых сценариев, в которых две сборки определяют одно и то же полное имя типа, используйте extern alias для дизамбигуации между ними.