Преимущество использования скобок для явного ограничения пространства имен состоит в том, что это задает определенный пользователем тип в реальном классе, определенном в файле, а не в самом файле. В Java файлы и папки косвенно представляют структуры языка, так как они аналогичны классам и пакетам, содержащим эти классы. В C# файлы не связаны принудительно с чем-либо, поэтому они становятся местом, где располагается определение класса, а не частью какой-либо структуры языка. Пространства имен также не связаны с папками. Следовательно, в одном файле можно ввести несколько пространств имен без всяких ограничений. Можно, например,
добавить определение нового класса и поместить его в новое пространство имен в том же файле и по-прежнему оставаться в границах языка:
// namespace_samples.cs
namespace Samples.On {
using System;
public class Example {
public Example {
}
}
}
namespace Com.Cslib {
using System;
using System.Collections;
public class AddLib {
public AddLib {
}
public int operationAdd(int a, int b) {
return a + b;
}
}
}
Пространства имен вводятся с помощью директивы
using <namespace name>
, где
<namespace name>
является именем пространства имен. В C# не требуется использовать
*
, так как директива
using
неявно импортирует все элементы указанного пространства имен. Другим преимуществом является то, что пространства имен могут быть добавлены исключительно в конкретный класс. Хотя классы
Example
и
AddLib
выше определены в файле
namespace_samples.cs
.
Example
не имеет доступа к пространству имен
System.Collections
, несмотря на то, что
AddLib
его имеет. Однако инструкция
import
из Java не является специфической для класса. Она импортирует указанные элементы в файл. Вновь обратимся к
х.java
.
// х.java
public class x {
}
class у {
}
class z {
}
Если добавить инструкцию импорта, такую как
import java.util.Hashtable
, все классы, определенные внутри этого файла, будут иметь доступ к классу
Hashtable
. Код ниже будет компилироваться:
// x.java
package samples;
import java.util.Hashtable;
public class x {
Hashtable hash = new Hashtable;
}
class у {
Hashtable hash = new Hashtable;
}
class z {
Hashtable hash = new Hashtable;
}
Пространства имен можно также определять внутри другого пространства имен. Этот тип гибкости недоступен в Java без создания подкаталогов. Приведенное выше пространство
Com.Cslib
можно расширить следующим образом:
namespace Com.Cslib {
using System;
public class AddLib {
public AddLib {
}
public int operationAdd(int a, int b) {
return a + b;
}
}
namespace Ext {
public class AddLib {
public AddLib {
}
public int operationAdd(int a, int b) {
return a + b;
}
}
}
}
Пакет Java
com.javalib
можно расширить, чтобы отобразить приведенный выше код, создав новую папку
\EXT
в каталоге
com\javalib
. В этой папке создается файл исходного кода
AddLib.java
следующим образом:
package com.javalib.ext;
public class AddLib {
public AddLib {
}
public int operationAdd(int a, int b) {
return a + b;
}
}
Отметим, что имя пакета было расширено для этого класса до
com.javalib.ext
.
Внутреннее пространство имен и подпакеты доступны с помощью оператора точки "."; следовательно, можно было в C# извлечь расширенный AddLib с помощью нотации
Com.Cslib.Ext.AddLib
. В Java можно было бы использовать
com.javalib.ext.AddLib
.
Приведенный выше пример показывает одно сходство между пакетами Java и пространствами имен C#. Даже если они не используются для внешнего представления, пространства имен, так же как и пакеты, предоставляют прекрасный способ создания глобально уникальных типов, свою собственную песочницу в мире сборок независимых поставщиков. В той степени насколько это имеет отношение к C#,
Com.Cslib.AddLib
является не тем же классом, что и
Com.Cslib.Ext.AddLib
.
Классы Java являются частью пакета, нравится им это или нет. Все классы, созданные без указания пакета, предполагают включение в пакет по умолчанию. C# имитирует эту функциональность. Даже если не объявить пространство имен, оно будет создано по умолчанию. Оно присутствует в каждом файле и доступно для использования в именованных пространствах имен. Так же как в Java нельзя изменить информацию о пакете, пространства имен нельзя модифицировать. Пакеты могут охватывать несколько файлов в одной папке, пространство имен может охватывать несколько файлов в любом числе папок и даже в нескольких сборках (сборки будут рассмотрены в следующем разделе). Два класса, охватываемые пространством имен А, которые определены в отдельных файлах и существуют в отдельных папках, оба являются частью пространства имен А.
Чтобы получить доступ к элементу в пространстве имен, необходимо либо использовать полностью квалифицированное имя типа (в приведенном выше примере это
Com.Cslib.AddLib
) или импортировать элемент пространства имен в текущее пространство имен, используя директиву
using
. Отметим, что по умолчанию доступность типов данных внутри пространства имен является внутренней. Необходимо явно отметить типы данных как открытые (
public
), если требуется сделать их доступными без полной квалификации, но придерживаться такой стратегии строго не рекомендуется. Никакие другие модификаторы доступа не разрешены. В Java внутренние типы пакета могут также помечаться как
final
или
abstract
, или не помечаться вообще (этот доступ по умолчанию открывает их только для потребителей внутри пакета). Модификаторы доступа будут рассматриваться позже в этом приложении.
Последним атрибутом, который относится к пространству имен, но не имеет отношения к пакетам, является возможность задания алиаса для
using
. Алиасы
using
существенно облегчают квалификацию идентификатора для пространства имен или класса. Синтаксис очень простой. Предположим, что имеется пространство имен