Как работают пространства имён (namespace) для одинаковых имён классов в C#
Что проверяют
Понимаете ли вы, как компилятор выбирает тип по короткому имени и что делать, когда два using приносят одинаковое имя. Следом часто спрашивают, чем пространство имён отличается от сборки.
Как отвечать
Пространство имён это часть полного имени типа, и существует оно для компилятора. В IL тип называется MyApp.Models.User, на производительность пространства имён не влияют. Со сборками связи нет: одна сборка содержит много пространств имён, одно пространство может быть разнесено по нескольким сборкам.
Два класса User в MyApp.Models и MyApp.Services уживаются спокойно. Проблема появляется в файле, где подключены оба using: короткое User даёт ошибку CS0104, неоднозначная ссылка. Способы развести:
- полное имя:
var u = new MyApp.Models.User();; - псевдоним:
using ServiceUser = MyApp.Services.User;. С C# 12 псевдоним можно дать любому типу, включая кортежи; global::: если в вашем коде есть класс или пространство с именемSystem, записьSystem.Consoleищется внутри него, аglobal::System.Consoleидёт от корня;extern alias: крайний случай, когда тип с одним и тем же полным именем лежит в двух сборках (ошибкаCS0433). Ссылке на сборку дают псевдоним в.csprojи обращаются черезAlias::Namespace.Type.
Назовите и порядок поиска: сначала текущее пространство имён и объемлющие, и на каждом уровне собственные типы побеждают импортированные через using. Поэтому свой класс Task в MyApp незаметно перекроет системный.
Из современного синтаксиса: file-scoped namespace MyApp.Models; и global using появились в C# 10, а в шаблонах проектов начиная с .NET 6 включены ImplicitUsings.
Где спотыкаются
Думают, что при двух using компилятор сам поймёт, какой User имеется в виду. Не поймёт, будет ошибка компиляции.
Путают пространство имён со сборкой и ищут причину CS0433 в директивах using, хотя дело в двух подключённых сборках с одинаковым типом.
Считают, что пространство имён обязано совпадать с папкой. Это соглашение, за ним следит анализатор IDE, компилятор его не требует.