9.5Namespace members
A namespace-member-declaration is either a namespace-declaration (§9.2) or a type-declaration (§9.6).
namespace-member-declarations:
namespace-member-declaration
namespace-member-declarations namespace-member-declaration
namespace-member-declaration:
namespace-declaration
type-declaration
A compilation unit or a namespace body can contain namespace-member-declarations, and such declarations contribute new members to the underlying declaration space of the containing compilation unit or namespace body.
9.6Type declarations
A type-declaration is a class-declaration (§10.1), a struct-declaration (§11.1), an interface-declaration (§13.1), an enum-declaration (§14.1), or a delegate-declaration (§15.1).
type-declaration:
class-declaration
struct-declaration
interface-declaration
enum-declaration
delegate-declaration
A type-declaration can occur as a top-level declaration in a compilation unit or as a member declaration within a namespace, class, or struct.
When a type declaration for a type T occurs as a top-level declaration in a compilation unit, the fully qualified name of the newly declared type is simply T. When a type declaration for a type T occurs within a namespace, class, or struct, the fully qualified name of the newly declared type is N.T, where N is the fully qualified name of the containing namespace, class, or struct.
A type declared within a class or struct is called a nested type (§10.3.8).
The permitted access modifiers and the default access for a type declaration depend on the context in which the declaration takes place (§3.5.1):
-
Types declared in compilation units or namespaces can have public or internal access. The default is internal access.
-
Types declared in classes can have public, protected internal, protected, internal, or private access. The default is private access.
-
Types declared in structs can have public, internal, or private access. The default is private access.
9.7Namespace alias qualifiers
The namespace alias qualifier :: makes it possible to guarantee that type name lookups are unaffected by the introduction of new types and members. The namespace alias qualifier always appears between two identifiers referred to as the left-hand and right-hand identifiers. Unlike the regular . qualifier, the left-hand identifier of the :: qualifier is looked up only as an extern or using alias.
A qualified-alias-member is defined as follows:
qualified-alias-member:
identifier :: identifier type-argument-listopt
A qualified-alias-member can be used as a namespace-or-type-name (§3.8) or as the left operand in a member-access (§7.5.4).
A qualified-alias-member has one of two forms:
Using this notation, the meaning of a qualified-alias-member is determined as follows:
-
If N is the identifier global, then the global namespace is searched for I:
-
If the global namespace contains a namespace named I and K is zero, then the qualified-alias-member refers to that namespace.
-
Otherwise, if the global namespace contains a non-generic type named I and K is zero, then the qualified-alias-member refers to that type.
-
Otherwise, if the global namespace contains a type named I that has K type parameters, then the qualified-alias-member refers to that type constructed with the given type arguments.
-
Otherwise, the qualified-alias-member is undefined and a compile-time error occurs.
-
Otherwise, starting with the namespace declaration (§9.2) immediately containing the qualified-alias-member (if any), continuing with each enclosing namespace declaration (if any), and ending with the compilation unit containing the qualified-alias-member, the following steps are evaluated until an entity is located:
-
If the namespace declaration or compilation unit contains a using-alias-directive that associates N with a type, then the qualified-alias-member is undefined and a compile-time error occurs.
-
Otherwise, if the namespace declaration or compilation unit contains an extern-alias-directive or using-alias-directive that associates N with a namespace, then:
-
If the namespace associated with N contains a namespace named I and K is zero, then the qualified-alias-member refers to that namespace.
-
Otherwise, if the namespace associated with N contains a non-generic type named I and K is zero, then the qualified-alias-member refers to that type.
-
Otherwise, if the namespace associated with N contains a type named I that has K type parameters, then the qualified-alias-member refers to that type constructed with the given type arguments.
-
Otherwise, the qualified-alias-member is undefined and a compile-time error occurs.
-
Otherwise, the qualified-alias-member is undefined and a compile-time error occurs.
Note that using the namespace alias qualifier with an alias that references a type causes a compile-time error. Also note that if the identifier N is global, then lookup is performed in the global namespace, even if there is a using alias associating global with a type or namespace.
9.7.1Uniqueness of aliases
Each compilation unit and namespace body has a separate declaration space for extern aliases and using aliases. Thus, while the name of an extern alias or using alias must be unique within the set of extern aliases and using aliases declared in the immediately containing compilation unit or namespace body, an alias is permitted to have the same name as a type or namespace as long as it is used only with the :: qualifier.
In the example
namespace N
{
public class A {}
public class B {}
}
namespace N
{
using A = System.IO;
class X
{
A.Stream s1; // Error, A is ambiguous
A::Stream s2; // Ok
}
}
the name A has two possible meanings in the second namespace body because both the class A and the using alias A are in scope. For this reason, use of A in the qualified name A.Stream is ambiguous and causes a compile-time error to occur. However, use of A with the :: qualifier is not an error because A is looked up only as a namespace alias.
Share with your friends: |