Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
14.1 General
Los programas de C# se organizan mediante espacios de nombres. Los espacios de nombres se usan como un sistema de organización "interno" para un programa y como un sistema de organización "externo", una forma de presentar elementos de programa que se exponen a otros programas.
Se proporcionan directivas using (§14.5) para facilitar el uso de espacios de nombres.
14.2 Unidades de compilación
Un compilation_unit consta de cero o más extern_alias_directiveseguidos de cero o más using_directiveseguidos de cero o de un global_attributes seguido de cero o más namespace_member_declarations. El compilation_unit define la estructura general de la entrada.
compilation_unit
: extern_alias_directive* using_directive* global_attributes?
namespace_member_declaration*
;
Un programa de C# consta de una o varias unidades de compilación. Cuando se compila un programa de C#, todas las unidades de compilación se procesan juntas. Por lo tanto, las unidades de compilación pueden depender entre sí, posiblemente de forma circular.
Los extern_alias_directivede una unidad de compilación afectan a los using_directives, global_attributes y namespace_member_declarationde esa unidad de compilación, pero no tienen ningún efecto en otras unidades de compilación.
Los using_directivede una unidad de compilación afectan al global_attributes y namespace_member_declarationde esa unidad de compilación, pero no tienen ningún efecto en otras unidades de compilación.
El global_attributes (§23.3) de una unidad de compilación permite la especificación de atributos para el ensamblado y el módulo de destino. Los ensamblados y módulos actúan como contenedores físicos para los tipos. Un ensamblado puede constar de varios módulos separados físicamente.
Los namespace_member_declarationde cada unidad de compilación de un programa contribuyen a los miembros a un único espacio de declaración denominado espacio de nombres global.
Example:
// File A.cs: class A {} // File B.cs: class B {}Las dos unidades de compilación contribuyen al único espacio de nombres global, en este caso declarando dos clases con los nombres
Acompletos yB. Dado que las dos unidades de compilación contribuyen al mismo espacio de declaración, habría sido un error si cada una contenía una declaración de un miembro con el mismo nombre.ejemplo final
14.3 Declaraciones de espacio de nombres
Un namespace_declaration consta del espacio de nombres de palabra clave, seguido de un nombre de espacio de nombres y un cuerpo, seguido opcionalmente de un punto y coma.
namespace_declaration
: 'namespace' qualified_identifier namespace_body ';'?
;
qualified_identifier
: identifier ('.' identifier)*
;
namespace_body
: '{' extern_alias_directive* using_directive*
namespace_member_declaration* '}'
;
Un namespace_declaration puede producirse como una declaración de nivel superior en un compilation_unit o como una declaración de miembro dentro de otro namespace_declaration. Cuando un namespace_declaration se produce como una declaración de nivel superior en un compilation_unit, el espacio de nombres se convierte en miembro del espacio de nombres global. Cuando se produce un namespace_declaration dentro de otro namespace_declaration, el espacio de nombres interno se convierte en miembro del espacio de nombres externo. En cualquier caso, el nombre de un espacio de nombres será único dentro del espacio de nombres contenedor.
Los espacios de nombres son implícitamente public y la declaración de un espacio de nombres no puede incluir ningún modificador de acceso.
Dentro de un namespace_body, el using_directiveopcional importa los nombres de otros espacios de nombres, tipos y miembros, lo que les permite hacer referencia directamente en lugar de mediante nombres calificados. Los namespace_member_declarationopcionales contribuyen a los miembros del espacio de declaraciones del espacio de nombres. Tenga en cuenta que todas las using_directiveaparecerán antes de cualquier declaración miembro.
El qualified_identifier de un namespace_declaration puede ser un identificador único o una secuencia de identificadores separados por tokens ".". Este último formulario permite a un programa definir un espacio de nombres anidado sin anidar léxicamente varias declaraciones de espacio de nombres.
Example:
namespace N1.N2 { class A {} class B {} }es semánticamente equivalente a
namespace N1 { namespace N2 { class A {} class B {} } }ejemplo final
Los espacios de nombres están abiertos y dos declaraciones de espacio de nombres con el mismo nombre completo (§7.8.3) contribuyen al mismo espacio de declaración (§7.3).
Ejemplo: en el código siguiente
namespace N1.N2 { class A {} } namespace N1.N2 { class B {} }las dos declaraciones de espacio de nombres anteriores contribuyen al mismo espacio de declaración, en este caso declarando dos clases con los nombres
N1.N2.Acompletos yN1.N2.B. Dado que las dos declaraciones contribuyen al mismo espacio de declaración, habría sido un error si cada una contenía una declaración de un miembro con el mismo nombre.ejemplo final
14.4 Directivas de alias extern
Un extern_alias_directive introduce un identificador que actúa como alias para un espacio de nombres. La especificación del espacio de nombres con alias es externa al código fuente del programa y también se aplica a los espacios de nombres anidados del espacio de nombres con alias.
extern_alias_directive
: 'extern' 'alias' identifier ';'
;
El ámbito de un extern_alias_directive se extiende a través de losusing_directive, global_attributes y namespace_member_declarations de su compilation_unit onamespace_body inmediatamente que contiene.
Dentro de una unidad de compilación o un cuerpo de espacio de nombres que contiene un extern_alias_directive, el identificador introducido por el extern_alias_directive se puede usar para hacer referencia al espacio de nombres con alias. Es un error en tiempo de compilación para que el identificador sea la palabra global.
El alias introducido por un extern_alias_directive es muy similar al alias introducido por un using_alias_directive. Consulte §14.5.2 para obtener información más detallada sobre extern_alias_directives y using_alias_directives.
alias es una palabra clave contextual (§6.4.4) y solo tiene un significado especial cuando sigue inmediatamente la extern palabra clave en un extern_alias_directive.
Se produce un error si un programa declara un alias extern para el que no se proporciona ninguna definición externa.
Ejemplo: el siguiente programa declara y usa dos alias extern,
XyY, cada uno de los cuales representa la raíz de una jerarquía de espacios de nombres distinto:extern alias X; extern alias Y; class Test { X::N.A a; X::N.B b1; Y::N.B b2; Y::N.C c; }El programa declara la existencia de los alias
Xde extern yY, pero las definiciones reales de los alias son externas al programa. Ahora se puede hacer referencia a las clases conN.Bnombre idéntico comoX.N.ByY.N.B, o , mediante el calificadorX::N.Bde alias de espacio de nombres yY::N.B. ejemplo final
14.5 Uso de directivas
14.5.1 General
Una directiva using facilita el uso de espacios de nombres y tipos definidos en otros espacios de nombres. El uso de directivas afecta al proceso de resolución de nombres de namespace_or_type_names (§7.8) y simple_names (§12.8.4), pero a diferencia de las declaraciones, using_directives no contribuyen nuevos miembros a los espacios de declaración subyacentes de las unidades de compilación o los espacios de nombres dentro de los que se usan.
using_directive
: using_alias_directive
| using_namespace_directive
| using_static_directive
;
Un using_alias_directive (§14.5.2) presenta un alias para un espacio de nombres o tipo.
Un using_namespace_directive (§14.5.3) importa los miembros de tipo de un espacio de nombres.
Un using_static_directive (§14.5.4) importa los tipos anidados y los miembros estáticos de un tipo.
El ámbito de un using_directive se extiende sobre el namespace_member_declarations de su unidad de compilación o cuerpo del espacio de nombres inmediatamente. El ámbito de un using_directive específicamente no incluye sus using_directivedel mismo nivel. Por lo tanto, la using_directivedel mismo nivel no afecta entre sí y el orden en el que se escriben es insignificante. En cambio, el ámbito de un extern_alias_directive incluye los using_directivedefinidos en la misma unidad de compilación o cuerpo del espacio de nombres.
14.5.2 Uso de directivas de alias
Un using_alias_directive introduce un identificador que actúa como alias para un espacio de nombres o un tipo dentro de la unidad de compilación o el cuerpo del espacio de nombres incluido inmediatamente.
using_alias_directive
: 'using' identifier '=' namespace_or_type_name ';'
;
Dentro de los atributos globales y las declaraciones de miembro de una unidad de compilación o un cuerpo de espacio de nombres que contiene un using_alias_directive, el identificador introducido por el using_alias_directive se puede usar para hacer referencia al espacio de nombres o al tipo especificados.
Example:
namespace N1.N2 { class A {} } namespace N3 { using A = N1.N2.A; class B: A {} }Anteriormente, dentro de las declaraciones de miembro del
N3espacio de nombres ,Aes un alias paraN1.N2.Ay, por tanto, la claseN3.Bderiva de la claseN1.N2.A. El mismo efecto se puede obtener creando un aliasRparaN1.N2y haciendo referencia aR.A:namespace N3 { using R = N1.N2; class B : R.A {} }ejemplo final
Dentro de las directivas using, los atributos globales y las declaraciones de miembro en una unidad de compilación o un cuerpo de espacio de nombres que contiene un extern_alias_directive, el identificador introducido por el extern_alias_directive se puede usar para hacer referencia al espacio de nombres asociado.
Ejemplo: por ejemplo:
namespace N1 { extern alias N2; class B : N2::A {} }Anteriormente, dentro de las declaraciones de miembro del
N1espacio de nombres,N2es un alias para algún espacio de nombres cuya definición es externa al código fuente del programa. La claseN1.Bderiva de la claseN2.A. El mismo efecto se puede obtener creando un aliasAparaN2.Ay haciendo referencia aA:namespace N1 { extern alias N2; using A = N2::A; class B : A {} }ejemplo final
Un extern_alias_directive o using_alias_directive hace que un alias esté disponible dentro de una unidad de compilación determinada o un cuerpo del espacio de nombres, pero no contribuye a ningún nuevo miembro al espacio de declaración subyacente. En otras palabras, una directiva de alias no es transitiva, sino que solo afecta al cuerpo de la unidad de compilación o del espacio de nombres en el que se produce.
Ejemplo: en el código siguiente
namespace N3 { extern alias R1; using R2 = N1.N2; } namespace N3 { class B : R1::A, R2.I {} // Error, R1 and R2 unknown }los ámbitos de las directivas de alias que introducen
R1yR2solo se extienden a las declaraciones de miembro en el cuerpo del espacio de nombres en el que se encuentran, por lo queR1yR2se desconocen en la segunda declaración de espacio de nombres. Sin embargo, colocar las directivas de alias en la unidad de compilación contenedora hace que el alias esté disponible en ambas declaraciones de espacio de nombres:extern alias R1; using R2 = N1.N2; namespace N3 { class B : R1::A, R2.I {} } namespace N3 { class C : R1::A, R2.I {} }ejemplo final
Cada extern_alias_directive o using_alias_directive en un compilation_unit o namespace_body contribuye a un nombre al espacio de declaración de alias (§7.3) del compilation_unit o namespace_body inmediatamente envolventes. El identificador de la directiva de alias será único dentro del espacio de declaración de alias correspondiente. El identificador de alias no debe ser único dentro del espacio de declaración global o el espacio de declaración del espacio de nombres correspondiente.
Example:
extern alias X; extern alias Y; using X = N1.N2; // Error: alias X already exists class Y {} // OkEl alias que usa el nombre
Xproduce un error, ya que ya hay un alias denominadoXen la misma unidad de compilación. La clase denominadaYno entra en conflicto con el alias extern denominadoY, ya que estos nombres se agregan a espacios de declaración distintos. El primero se agrega al espacio de declaración global y este último se agrega al espacio de declaración de alias para esta unidad de compilación.Cuando un nombre de alias coincide con el nombre de un miembro de un espacio de nombres, el uso de cualquiera de los dos se calificará adecuadamente:
namespace N1.N2 { class B {} } namespace N3 { class A {} class B : A {} } namespace N3 { using A = N1.N2; using B = N1.N2.B; class W : B {} // Error: B is ambiguous class X : A.B {} // Error: A is ambiguous class Y : A::B {} // Ok: uses N1.N2.B class Z : N3.B {} // Ok: uses N3.B }En el segundo cuerpo del espacio de nombres para
N3, el uso no completo deBda como resultado un error, ya queN3contiene un miembro denominadoBy el cuerpo del espacio de nombres que también declara un alias con nombreB; del mismo modo paraA. Se puede hacer referencia a la claseN3.BcomoN3.Boglobal::N3.B. El aliasAse puede usar en un miembro calificado de alias (§14.8), comoA::B. El aliasBes esencialmente inútil. No se puede usar en un qualified_alias_member , ya que solo se pueden usar alias de espacio de nombres en un qualified_alias_member yBalias de un tipo.ejemplo final
Al igual que los miembros normales, los nombres introducidos por alias_directives están ocultos por miembros con nombre similar en ámbitos anidados.
Ejemplo: en el código siguiente
using R = N1.N2; namespace N3 { class R {} class B: R.A {} // Error, R has no member A }la referencia a
R.Aen la declaración de produce un error en tiempo deBcompilación porqueRhace referencia aN3.R, noN1.N2a .ejemplo final
El orden en que se escriben extern_alias_directiveno tiene importancia. Del mismo modo, el orden en que se escriben using_alias_directiveno tiene ningún significado, pero todos los using_alias_directives deberán aparecer después de todos los extern_alias_directiveen la misma unidad de compilación o cuerpo del espacio de nombres. La resolución de la namespace_or_type_name a la que hace referencia un using_alias_directive no se ve afectada por el propio using_alias_directive o por otros using_directives en el cuerpo de la unidad de compilación o espacio de nombres inmediatamente que contiene, pero puede verse afectado por extern_alias_directives en el cuerpo de la unidad de compilación o del espacio de nombres inmediatamente contenedor. Es decir, el namespace_or_type_name de un using_alias_directive se resuelve como si el cuerpo de la unidad de compilación o del espacio de nombres que contiene inmediatamente no tuviera using_directives, pero tiene el conjunto correcto de extern_alias_directives.
Ejemplo: en el código siguiente
namespace N1.N2 {} namespace N3 { extern alias X; using R1 = X::N; // OK using R2 = N1; // OK using R3 = N1.N2; // OK using R4 = R2.N2; // Error, R2 unknown }el último using_alias_directive produce un error en tiempo de compilación porque no se ve afectado por el using_alias_directive anterior. El primer using_alias_directive no produce un error, ya que el ámbito del alias X de extern incluye el using_alias_directive.
ejemplo final
Un using_alias_directive puede crear un alias para cualquier espacio de nombres o tipo, incluido el espacio de nombres en el que aparece y cualquier espacio de nombres o tipo anidado dentro de ese espacio de nombres.
El acceso a un espacio de nombres o un tipo a través de un alias produce exactamente el mismo resultado que el acceso a ese espacio de nombres o tipo a través de su nombre declarado.
Ejemplo: Dado
namespace N1.N2 { class A {} } namespace N3 { using R1 = N1; using R2 = N1.N2; class B { N1.N2.A a; // refers to N1.N2.A R1.N2.A b; // refers to N1.N2.A R2.A c; // refers to N1.N2.A } }los nombres
N1.N2.A,R1.N2.Ay son equivalentes yR2.Atodos hacen referencia a la declaración de clase cuyo nombre completo esN1.N2.A.ejemplo final
Aunque cada parte de un tipo parcial (§15.2.7) se declara dentro del mismo espacio de nombres, las partes normalmente se escriben en diferentes declaraciones de espacio de nombres. Por lo tanto, se pueden presentar diferentes extern_alias_directives y using_directivepara cada parte. Al interpretar nombres simples (§12.8.4) dentro de una parte, solo se consideran los extern_alias_directives y using_directivede los cuerpos del espacio de nombres y la unidad de compilación que incluye esa parte. Esto puede dar lugar a que el mismo identificador tenga significados diferentes en partes diferentes.
Example:
namespace N { using List = System.Collections.ArrayList; partial class A { List x; // x has type System.Collections.ArrayList } } namespace N { using List = Widgets.LinkedList; partial class A { List y; // y has type Widgets.LinkedList } }ejemplo final
El uso de alias puede asignar un nombre a un tipo construido cerrado, pero no puede asignar un nombre a una declaración de tipo genérico sin proporcionar argumentos de tipo.
Example:
namespace N1 { class A<T> { class B {} } } namespace N2 { using W = N1.A; // Error, cannot name unbound generic type using X = N1.A.B; // Error, cannot name unbound generic type using Y = N1.A<int>; // Ok, can name closed constructed type using Z<T> = N1.A<T>; // Error, using alias cannot have type parameters }ejemplo final
14.5.3 Uso de directivas de espacio de nombres
Un using_namespace_directive importa los tipos contenidos en un espacio de nombres en el cuerpo de la unidad de compilación o espacio de nombres inmediatamente envolvente, lo que permite usar el identificador de cada tipo sin cualificación.
using_namespace_directive
: 'using' namespace_name ';'
;
Dentro de las declaraciones de miembro de una unidad de compilación o un cuerpo de espacio de nombres que contiene un using_namespace_directive, se puede hacer referencia directamente a los tipos contenidos en el espacio de nombres especificado.
Example:
namespace N1.N2 { class A {} } namespace N3 { using N1.N2; class B : A {} }Anteriormente, dentro de las declaraciones de miembro del
N3espacio de nombres, los miembros de tipo deN1.N2están disponibles directamente y, por tanto, la claseN3.Bderiva de la claseN1.N2.A.ejemplo final
Un using_namespace_directive importa los tipos contenidos en el espacio de nombres especificado, pero específicamente no importa espacios de nombres anidados.
Ejemplo: en el código siguiente
namespace N1.N2 { class A {} } namespace N3 { using N1; class B : N2.A {} // Error, N2 unknown }el using_namespace_directive importa los tipos contenidos en
N1, pero no los espacios de nombres anidados enN1. Por lo tanto, la referencia aN2.Aen la declaración de da como resultado un error en tiempo deBcompilación porque ningún miembro denominadoN2está en el ámbito.ejemplo final
A diferencia de un using_alias_directive, un using_namespace_directive puede importar tipos cuyos identificadores ya están definidos dentro de la unidad de compilación envolvente o el cuerpo del espacio de nombres. En efecto, los nombres importados por un using_namespace_directive están ocultos por miembros con nombre similar en el cuerpo de la unidad de compilación o del espacio de nombres envolvente.
Example:
namespace N1.N2 { class A {} class B {} } namespace N3 { using N1.N2; class A {} }Aquí, dentro de las declaraciones de miembro del
N3espacio de nombres,Ahace referencia aN3.Aen lugar deN1.N2.Aa .ejemplo final
Dado que los nombres pueden ser ambiguos cuando más de un espacio de nombres importado introduce el mismo nombre de tipo, un using_alias_directive es útil para desambiguar la referencia.
Ejemplo: en el código siguiente
namespace N1 { class A {} } namespace N2 { class A {} } namespace N3 { using N1; using N2; class B : A {} // Error, A is ambiguous }
N1yN2contienen un miembroA, y porqueN3importa ambos, hacer referenciaAa en es un error enN3tiempo de compilación. En esta situación, el conflicto se puede resolver a través de la calificación de referencias aAo introduciendo un using_alias_directive que elige un determinadoA. Por ejemplo:namespace N3 { using N1; using N2; using A = N1.A; class B : A {} // A means N1.A }ejemplo final
Además, cuando más de un espacio de nombres o tipo importado por using_namespace_directives o using_static_directives en la misma unidad de compilación o cuerpo del espacio de nombres contienen tipos o miembros por el mismo nombre, las referencias a ese nombre como un simple_name se consideran ambiguas.
Example:
namespace N1 { class A {} } class C { public static int A; } namespace N2 { using N1; using static C; class B { void M() { A a = new A(); // Ok, A is unambiguous as a type-name A.Equals(2); // Error, A is ambiguous as a simple-name } } }
N1contiene un miembroAde tipo yCcontiene un campoAestático y, dado queN2importa ambos, hacer referenciaAa un simple_name es ambiguo y un error en tiempo de compilación.ejemplo final
Al igual que un using_alias_directive, un using_namespace_directive no contribuye a ningún nuevo miembro al espacio de declaración subyacente de la unidad de compilación o el espacio de nombres, sino que, en su lugar, afecta solo al cuerpo de la unidad de compilación o del espacio de nombres en el que aparece.
El namespace_name al que hace referencia un using_namespace_directive se resuelve de la misma manera que el namespace_or_type_name al que hace referencia un using_alias_directive. Por lo tanto, using_namespace_directiveen la misma unidad de compilación o cuerpo del espacio de nombres no afectan entre sí y se pueden escribir en cualquier orden.
14.5.4 Uso de directivas estáticas
Un using_static_directive importa los tipos anidados y los miembros estáticos contenidos directamente en una declaración de tipo en el cuerpo de espacio de nombres o unidad de compilación envolvente inmediatamente, lo que permite usar el identificador de cada miembro y tipo sin cualificación.
using_static_directive
: 'using' 'static' type_name ';'
;
Dentro de las declaraciones de miembro de una unidad de compilación o un cuerpo de espacio de nombres que contiene un using_static_directive, se puede hacer referencia directamente a los tipos anidados y a los miembros estáticos accesibles (excepto los métodos de extensión) contenidos directamente en la declaración del tipo especificado.
Example:
namespace N1 { class A { public class B {} public static B M() => new B(); } } namespace N2 { using static N1.A; class C { void N() { B b = M(); } } }En el código anterior, dentro de las declaraciones de miembro del
N2espacio de nombres, los miembros estáticos y los tipos anidados deN1.Aestán disponibles directamente y, por tanto, el métodoNpuede hacer referencia a losBmiembros yMdeN1.A.ejemplo final
Un using_static_directive específicamente no importa métodos de extensión directamente como métodos estáticos, pero hace que estén disponibles para la invocación del método de extensión (§12.8.10.3).
Example:
namespace N1 { static class A { public static void M(this string s){} } } namespace N2 { using static N1.A; class B { void N() { M("A"); // Error, M unknown "B".M(); // Ok, M known as extension method N1.A.M("C"); // Ok, fully qualified } } }el using_static_directive importa el método
Mde extensión contenido enN1.A, pero solo como un método de extensión. Por lo tanto, la primera referencia aMen el cuerpo de da como resultado un error en tiempo deB.Ncompilación porque ningún miembro denominadoMestá en el ámbito.ejemplo final
Un using_static_directive solo importa miembros y tipos declarados directamente en el tipo especificado, no miembros y tipos declarados en clases base.
Example:
namespace N1 { class A { public static void M(string s){} } class B : A { public static void M2(string s){} } } namespace N2 { using static N1.B; class C { void N() { M2("B"); // OK, calls B.M2 M("C"); // Error. M unknown } } }el using_static_directive importa el método
M2contenido enN1.B, pero no importa el métodoMcontenido enN1.A. Por lo tanto, la referencia aMen el cuerpo de da como resultado un error en tiempo deC.Ncompilación porque ningún miembro denominadoMestá en el ámbito. Los desarrolladores deben agregar una segundausing staticdirectiva para especificar que los métodos deN1.Atambién deben importarse.ejemplo final
Las ambigüedades entre varios using_namespace_directives y using_static_directives se describen en §14.5.3.
14.6 Declaraciones de miembro de espacio de nombres
Un namespace_member_declaration es un namespace_declaration (§14.3) o un type_declaration (§14.7).
namespace_member_declaration
: namespace_declaration
| type_declaration
;
Una unidad de compilación o un cuerpo de espacio de nombres puede contener namespace_member_declarations, y estas declaraciones contribuyen a nuevos miembros al espacio de declaración subyacente de la unidad de compilación o el cuerpo del espacio de nombres que contiene.
14.7 Declaraciones de tipo
Un type_declaration es un class_declaration (§15.2), un struct_declaration (§16.2), un interface_declaration (§19.2), un enum_declaration (§20.2) o un delegate_declaration (§21.2).
type_declaration
: class_declaration
| struct_declaration
| interface_declaration
| enum_declaration
| delegate_declaration
;
Un type_declaration puede producirse como una declaración de nivel superior en una unidad de compilación o como declaración de miembro dentro de un espacio de nombres, una clase o un struct.
Cuando una declaración de tipo para un tipo T se produce como una declaración de nivel superior en una unidad de compilación, el nombre completo (§7.8.3) de la declaración de tipo es el mismo que el nombre no completo de la declaración (§7.8.2). Cuando se produce una declaración de tipo para un tipo T dentro de una declaración de espacio de nombres, clase o estructura, el nombre completo (§7.8.3) de la declaración de tipo es S.N, donde S es el nombre completo del espacio de nombres contenedor, la clase o la declaración struct, y N es el nombre no completo de la declaración.
Un tipo declarado dentro de una clase, interfaz o estructura se denomina un tipo anidado (§15.3.9).
Los modificadores de acceso permitidos y el acceso predeterminado para una declaración de tipo dependen del contexto en el que tiene lugar la declaración (§7.5.2):
- Los tipos declarados en unidades de compilación o espacios de nombres pueden tener
publicointernaltener acceso. El valor predeterminado esinternalel acceso. - Los tipos declarados en clases pueden tener
publicacceso a ,protected internal,protected,private protected, ,internaloprivate. El valor predeterminado esprivateel acceso. - Los tipos declarados en estructuras pueden tener
publicacceso a ,internaloprivate. El valor predeterminado esprivateel acceso.
14.8 Miembro de alias calificado
14.8.1 General
El de alias de espacio de nombres permite garantizar que las búsquedas de nombres de tipo no se ven afectadas por la introducción de nuevos tipos y miembros. El calificador de alias de espacio de nombres siempre aparece entre dos identificadores denominados identificadores izquierdo y derecho. A diferencia del calificador normal . , el identificador izquierdo del :: calificador solo se busca como un extern o mediante alias.
Un qualified_alias_member proporciona acceso explícito al espacio de nombres global y a extern o mediante alias que pueden ocultar otras entidades.
qualified_alias_member
: identifier '::' identifier type_argument_list?
;
Un qualified_alias_member se puede usar como namespace_or_type_name (§7.8) o como operando izquierdo en un member_access (§12.8.7).
Un qualified_alias_member consta de dos identificadores, denominados identificadores izquierdo y derecho, separados por el :: token y, opcionalmente, seguidos de un type_argument_list. Cuando el identificador izquierdo es global, el espacio de nombres global se busca en el identificador derecho. Para cualquier otro identificador izquierdo, ese identificador se busca como un extern o mediante alias (§14.4 y §14.5.2). Se produce un error en tiempo de compilación si no hay ese alias o el alias hace referencia a un tipo. Si el alias hace referencia a un espacio de nombres, ese espacio de nombres se busca en el identificador derecho.
Un qualified_alias_member tiene una de estas dos formas:
-
N::I<A₁, ..., Aₑ>, dondeNyIrepresentan identificadores, y<A₁, ..., Aₑ>es una lista de argumentos de tipo. (esiempre es al menos uno). -
N::I, dondeNyIrepresentan identificadores. (En este caso,ese considera cero).
Con esta notación, el significado de un qualified_alias_member se determina de la siguiente manera:
- Si
Nes el identificadorglobal, se buscaIen el espacio de nombres global :- Si el espacio de nombres global contiene un espacio de nombres denominado
Iyees cero, el qualified_alias_member hace referencia a ese espacio de nombres. - De lo contrario, si el espacio de nombres global contiene un tipo no genérico denominado
Iyees cero, el qualified_alias_member hace referencia a ese tipo. - De lo contrario, si el espacio de nombres global contiene un tipo denominado
Ique tieneeparámetros de tipo, el qualified_alias_member hace referencia a ese tipo construido con los argumentos de tipo especificados. - De lo contrario, el qualified_alias_member no está definido y se produce un error en tiempo de compilación.
- Si el espacio de nombres global contiene un espacio de nombres denominado
- De lo contrario, a partir de la declaración de espacio de nombres (§14.3) que contiene inmediatamente el qualified_alias_member (si existe), continuando con cada declaración de espacio de nombres envolvente (si existe) y finalizando con la unidad de compilación que contiene el qualified_alias_member, se evalúan los pasos siguientes hasta que se encuentra una entidad:
- Si la declaración de espacio de nombres o la unidad de compilación contiene un using_alias_directive que asocia N a un tipo, el qualified_alias_member no está definido y se produce un error en tiempo de compilación.
- De lo contrario, si la declaración de espacio de nombres o la unidad de compilación contiene un extern_alias_directive o using_alias_directive que se asocia
Na un espacio de nombres, a continuación:- Si el espacio de nombres asociado a
Ncontiene un espacio de nombres denominadoIyees cero, el qualified_alias_member hace referencia a ese espacio de nombres. - De lo contrario, si el espacio de nombres asociado a
Ncontiene un tipo no genérico denominadoIyees cero, el qualified_alias_member hace referencia a ese tipo. - De lo contrario, si el espacio de nombres asociado a
Ncontiene un tipo denominadoIque tiene parámetros de tipoe, el qualified_alias_member hace referencia a ese tipo construido con los argumentos de tipo especificados. - De lo contrario, el qualified_alias_member no está definido y se produce un error en tiempo de compilación.
- Si el espacio de nombres asociado a
- De lo contrario, el qualified_alias_member no está definido y se produce un error en tiempo de compilación.
Ejemplo: en el código:
using S = System.Net.Sockets; class A { public static int x; } class C { public void F(int A, object S) { // Use global::A.x instead of A.x global::A.x += A; // Use S::Socket instead of S.Socket S::Socket s = S as S::Socket; } }se hace referencia a la clase
Aconglobal::Ay se hace referencia al tipoSystem.Net.Sockets.SocketconS::Socket. El usoA.xde yS.Socketen su lugar habría provocado errores en tiempo de compilación porqueAySse habrían resuelto en los parámetros.ejemplo final
Nota: El identificador
globaltiene un significado especial solo cuando se usa como identificador izquierdo de un qualified_alias_name. No es una palabra clave y no es en sí mismo un alias; es una palabra clave contextual (§6.4.4). En el código:class A { } class C { global.A x; // Error: global is not defined global::A y; // Valid: References A in the global namespace }using
global.Aproduce un error en tiempo de compilación, ya que no hay ninguna entidad denominadaglobalen el ámbito. Si alguna entidad denominada global estuviera en el ámbito,globalenglobal.Ahabría resuelto esa entidad.El uso
globalde como identificador izquierdo de un qualified_alias_member siempre provoca una búsqueda en elglobalespacio de nombres, incluso si hay un alias con el nombreglobal. En el código:using global = MyGlobalTypes; class A { } class C { global.A x; // Valid: References MyGlobalTypes.A global::A y; // Valid: References A in the global namespace }
global.Ase resuelve enMyGlobalTypes.Ayglobal::Ase resuelve en la claseAen el espacio de nombres global.nota final
14.8.2 Unicidad de alias
Cada unidad de compilación y cuerpo del espacio de nombres tiene un espacio de declaración independiente para alias extern y el uso de alias. Por lo tanto, aunque el nombre de un alias extern o el uso de alias debe ser único dentro del conjunto de alias extern y el uso de alias declarados en el cuerpo de la unidad de compilación o espacio de nombres inmediatamente que contiene, se permite que un alias tenga el mismo nombre que un tipo o espacio de nombres siempre que solo se use con el :: calificador.
Ejemplo: En lo siguiente:
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 } }el nombre
Atiene dos significados posibles en el segundo cuerpo del espacio de nombres porque tanto la claseAcomo el aliasAusing están en el ámbito. Por este motivo, el uso deAen el nombreA.Streamcompleto es ambiguo y hace que se produzca un error en tiempo de compilación. Sin embargo, el uso deAcon el::calificador no es un error porqueAsolo se busca como alias de espacio de nombres.ejemplo final
ECMA C# draft specification