Пространства имен
43C# --- Сборки .NET --- Пространства имен
Прежде чем углубляться в детали развертывания и конфигурирования сборок, сначала необходимо узнать о том, как создавать специальные пространства имен в .NET. При создании собственных приложений, однако, может быть удобно группировать свои взаимосвязанные типы в специальные пространства имен. В C# это делается с помощью ключевого слова namespace. Определение специальных пространств имен явным образом начинает играть даже еще более важную роль при создании dll-сборок в .NET, поскольку другие разработчики должны иметь возможность импортировать эти специальные пространства имен, чтобы использовать содержащиеся в них типы.
Пространство имен определяет область объявлений, в которой допускается хранить одно множество имен отдельно от другого. По существу, имена, объявленные в одном пространстве имен, не будут вступать в конфликт с аналогичными именами, объявленными в другой области. Так, в библиотеке классов для среды .NET Framework, которая одновременно является библиотекой классов C#, используется пространство имен System.
Ниже приведена общая форма объявления пространства имен:
namespace имя { // члены }
Давайте рассмотрим пример:
using System;
// Объявляем новое пространство имен, описывающее классы фигур
// Файл MyShapes.cs
namespace ShapesMyProgramm
{
class Circle
{
public double Radius { get; set; }
public Circle(double r)
{
Radius = r;
}
public void Square()
{
Console.WriteLine("Площадь круга = {0:#.###}",Math.PI*Radius*Radius);
}
public void Long()
{
Console.WriteLine("Длина круга = {0:#.##}",Math.PI*2*Radius);
}
}
class Rectangle
{
public int a { get; set; }
public int b { get; set; }
public Rectangle(int a, int b)
{
this.a = a;
this.b = b;
}
public void Square()
{
Console.WriteLine("Площадь прямоугольника = "+a*b);
}
public void Long()
{
Console.WriteLine("Длина прямоугольника = "+(2*a+2*b));
}
}
}
// Файл Program.cs
using System;
using ShapesMyProgramm; // Используем объявленное пространство имен
namespace ConsoleApplication1
{
class Program
{
static void Main()
{
Circle c1 = new Circle(r: 12.0);
Rectangle rec1 = new Rectangle(a: 5, b: 4);
c1.Square();
c1.Long();
rec1.Square();
rec1.Long();
Console.ReadLine();
}
}
}
В этом примере предполагается, что файл (или файлы) с кодом C#, в котором содержится определение пространства имен ShapesMyProgramm, является частью того же проекта типа Console Application, что и файл с определением пространства имен ConsoleApplication1. Другими словами, все эти файлы будут использоваться для компиляции единственной исполняемой сборки .NET.
Если пространство имен ShapesMyProgramm определено внутри какой-то внешней сборки, для успешной компиляции может потребоваться добавить ссылку на эту библиотеку.
Предотвращение конфликтов имен с помощью пространств имен
С технической точки зрения применять в C# ключевое слово using при ссылках на типы, определенные во внешних пространствах имен, вовсе не требуется. Вместо этого можно использовать полностью уточненное имя типа, под которым понимается имя типа с идущим перед ним в качестве префикса названием пространства имен, где этот тип определен. Так код файла Program.cs можно видоизменить следующим образом:
static void Main()
{
ShapesMyProgramm.Circle c1 = new ShapesMyProgramm.Circle(r: 12.0);
ShapesMyProgramm.Rectangle rec1 = new ShapesMyProgramm.Rectangle(a: 5, b: 4);
c1.Square();
c1.Long();
rec1.Square();
rec1.Long();
Console.ReadLine();
}
Обычно необходимости в применении полностью уточненного имени не возникает. Это требует большего объема клавиатурного ввода, при этом никак не влияет на размер и скорость выполнения кода. С другой стороны, в CIL-коде типы всегда определяются с использованием полностью уточненных имен. В результате применение в C# ключевого слова using, по сути, позволяет просто экономить время.
Тем не менее, иногда применение полностью уточненных имен может оказываться очень удобным (а то и вообще необходимым) для избегания конфликтов на уровне имен, которые могут возникать при использовании множества пространств имен и наличии в этих пространствах имен одинаково названных типов.
В C# ключевое слово using также позволяет создавать псевдоним для полностью уточненного имени типа. В этом случае определяется маркер, на месте которого во время компиляции должно подставляться полностью уточненное имя. Определение псевдонимов является вторым способом разрешения конфликтов на уровне имен:
// Файл Program.cs
using System;
// Создание псевдонима
using ShapeCircle = ShapesMyProgramm.Circle;
namespace ConsoleApplication1
{
class Program
{
static void Main()
{
// Использование псевдонима
ShapeCircle c1 = new ShapesMyProgramm.Circle(r: 12.0);
ShapesMyProgramm.Rectangle rec1 = new ShapesMyProgramm.Rectangle(a: 5, b: 4);
c1.Square();
c1.Long();
rec1.Square();
rec1.Long();
Console.ReadLine();
}
}
}
Ключевое слово using в C# позволяет создавать псевдонимы для длинных полностью уточненных имен и потому может применяться для разрешения конфликтов на уровне имен, которые могут возникать в результате импорта пространств имен, содержащих типы с идентичными именами.
Применение описателя псевдонима пространства имен
Пространства имен помогают предотвратить конфликты имен, но не устранить их полностью. Такой конфликт может, в частности, произойти, когда одно и то же имя объявляется в двух разных пространствах имен и затем предпринимается попытка сделать видимыми оба пространства. Допустим, что два пространства имен содержат класс MyClass. Если попытаться сделать видимыми оба пространства имен с помощью директивы using, то имя MyClass из первого пространства вступит в конфликт с именем MyClass из второго пространства, обусловив появление ошибки неоднозначности. В таком случае для указания предполагаемого пространства имен явным образом можно воспользоваться описателем псевдонима пространства имен ::.
Ниже приведена общая форма оператора ::.
псевдоним_пространства_имен :: идентификатор
Здесь псевдоним_пространства_имен обозначает конкретное имя псевдонима пространства имен, а идентификатор — имя члена этого пространства.