Conceptos básicosBasic concepts

Inicio de la aplicaciónApplication Startup

Un ensamblado que tiene un punto de entrada se denomina aplicación.An assembly that has an entry point is called an application. Cuando se ejecuta una aplicación, se crea un nuevo dominio de aplicación .When an application is run, a new application domain is created. Puede haber varias instancias diferentes de una aplicación en el mismo equipo al mismo tiempo, y cada una tiene su propio dominio de aplicación.Several different instantiations of an application may exist on the same machine at the same time, and each has its own application domain.

Un dominio de aplicación permite el aislamiento de aplicaciones actuando como un contenedor para el estado de la aplicación.An application domain enables application isolation by acting as a container for application state. Un dominio de aplicación actúa como contenedor y límite para los tipos definidos en la aplicación y las bibliotecas de clases que usa.An application domain acts as a container and boundary for the types defined in the application and the class libraries it uses. Los tipos que se cargan en un dominio de aplicación son distintos del mismo tipo cargado en otro dominio de aplicación y las instancias de objetos no se comparten directamente entre los dominios de aplicación.Types loaded into one application domain are distinct from the same type loaded into another application domain, and instances of objects are not directly shared between application domains. Por ejemplo, cada dominio de aplicación tiene su propia copia de variables estáticas para estos tipos, y un constructor estático para un tipo se ejecuta como máximo una vez por dominio de aplicación.For instance, each application domain has its own copy of static variables for these types, and a static constructor for a type is run at most once per application domain. Las implementaciones son gratuitas para proporcionar directivas específicas de implementación o mecanismos para la creación y destrucción de dominios de aplicación.Implementations are free to provide implementation-specific policy or mechanisms for the creation and destruction of application domains.

El inicio de la aplicación se produce cuando el entorno de ejecución llama a un método designado, al que se hace referencia como punto de entrada de la aplicación.Application startup occurs when the execution environment calls a designated method, which is referred to as the application's entry point. Este método de punto de entrada siempre se denomina Main y puede tener una de las firmas siguientes:This entry point method is always named Main, and can have one of the following signatures:

static void Main() {...}

static void Main(string[] args) {...}

static int Main() {...}

static int Main(string[] args) {...}

Como se muestra, el punto de entrada puede devolver opcionalmente un valor int.As shown, the entry point may optionally return an int value. Este valor devuelto se usa en la finalización de la aplicación (finalizaciónde la aplicación).This return value is used in application termination (Application termination).

El punto de entrada puede tener opcionalmente un parámetro formal.The entry point may optionally have one formal parameter. El parámetro puede tener cualquier nombre, pero el tipo del parámetro debe ser string[].The parameter may have any name, but the type of the parameter must be string[]. Si el parámetro formal está presente, el entorno de ejecución crea y pasa un argumento string[] que contiene los argumentos de la línea de comandos que se especificaron al iniciarse la aplicación.If the formal parameter is present, the execution environment creates and passes a string[] argument containing the command-line arguments that were specified when the application was started. El argumento string[] nunca es null, pero puede tener una longitud de cero si no se especificó ningún argumento de línea de comandos.The string[] argument is never null, but it may have a length of zero if no command-line arguments were specified.

Puesto C# que admite la sobrecarga de métodos, una clase o struct puede contener varias definiciones de algún método, siempre que cada una tenga una firma diferente.Since C# supports method overloading, a class or struct may contain multiple definitions of some method, provided each has a different signature. Sin embargo, dentro de un único programa, ninguna clase o struct puede contener más de un método llamado Main cuya definición se pueda usar como punto de entrada de la aplicación.However, within a single program, no class or struct may contain more than one method called Main whose definition qualifies it to be used as an application entry point. No obstante, se permiten otras versiones sobrecargadas de Main, siempre y cuando tengan más de un parámetro, o su único parámetro sea distinto del tipo string[].Other overloaded versions of Main are permitted, however, provided they have more than one parameter, or their only parameter is other than type string[].

Una aplicación puede estar formada por varias clases o Structs.An application can be made up of multiple classes or structs. Es posible que más de una de estas clases o Structs contengan un método denominado Main cuya definición sea apta para su uso como punto de entrada de la aplicación.It is possible for more than one of these classes or structs to contain a method called Main whose definition qualifies it to be used as an application entry point. En tales casos, se debe usar un mecanismo externo (como una opción del compilador de línea de comandos) para seleccionar uno de estos métodos Main como punto de entrada.In such cases, an external mechanism (such as a command-line compiler option) must be used to select one of these Main methods as the entry point.

En C#, cada método se debe definir como miembro de una clase o struct.In C#, every method must be defined as a member of a class or struct. Normalmente, la accesibilidad declarada (accesibilidad declarada) de un método viene determinada por los modificadores de acceso (modificadores de acceso) especificados en su declaración y, de igual forma, la accesibilidad declarada de un tipo viene determinada por la modificadores de acceso especificados en su declaración.Ordinarily, the declared accessibility (Declared accessibility) of a method is determined by the access modifiers (Access modifiers) specified in its declaration, and similarly the declared accessibility of a type is determined by the access modifiers specified in its declaration. Para que se pueda llamar a un método dado de un tipo determinado, tanto el tipo como el miembro deben ser accesibles.In order for a given method of a given type to be callable, both the type and the member must be accessible. Sin embargo, el punto de entrada de la aplicación es un caso especial.However, the application entry point is a special case. En concreto, el entorno de ejecución puede tener acceso al punto de entrada de la aplicación, independientemente de su accesibilidad declarada y sin tener en consideración la accesibilidad declarada de sus declaraciones de tipos envolventes.Specifically, the execution environment can access the application's entry point regardless of its declared accessibility and regardless of the declared accessibility of its enclosing type declarations.

Es posible que el método de punto de entrada de la aplicación no esté en una declaración de clase genérica.The application entry point method may not be in a generic class declaration.

En todos los demás aspectos, los métodos de punto de entrada se comportan como los que no son puntos de entrada.In all other respects, entry point methods behave like those that are not entry points.

Finalización de la aplicaciónApplication termination

La finalización de la aplicación devuelve el control al entorno de ejecución.Application termination returns control to the execution environment.

Si el tipo de valor devuelto del método de punto de entrada de la aplicación es int, el valor devuelto actúa como el código de Estado de terminaciónde la aplicación.If the return type of the application's entry point method is int, the value returned serves as the application's termination status code. El propósito de este código es permitir la comunicación de éxito o error en el entorno de ejecución.The purpose of this code is to allow communication of success or failure to the execution environment.

Si el tipo de valor devuelto del método de punto de entrada es void, al llegar a la llave de cierre (}) que finaliza ese método o al ejecutar una instrucción @no__t 2 que no tiene ninguna expresión, se genera un código de estado de finalización de 0.If the return type of the entry point method is void, reaching the right brace (}) which terminates that method, or executing a return statement that has no expression, results in a termination status code of 0.

Antes de la terminación de una aplicación, se llama a los destructores para todos sus objetos que todavía no se han recolectado como elemento no utilizado, a menos que se haya suprimido dicha limpieza (mediante una llamada al método de biblioteca GC.SuppressFinalize, por ejemplo).Prior to an application's termination, destructors for all of its objects that have not yet been garbage collected are called, unless such cleanup has been suppressed (by a call to the library method GC.SuppressFinalize, for example).

DeclaracionesDeclarations

Las declaraciones de un C# programa definen los elementos constituyentes del programa.Declarations in a C# program define the constituent elements of the program. C#los programas se organizan mediante espacios de nombres (espaciosde nombres), que pueden contener declaraciones de tipos y declaraciones de espacio de nombres anidadas.C# programs are organized using namespaces (Namespaces), which can contain type declarations and nested namespace declarations. Las declaraciones de tipos (declaraciones de tipo) se utilizan para definir clases (clases), Structs (Structs), interfaces (interfaces), enumeraciones (enumeraciones) y delegados (delegados).Type declarations (Type declarations) are used to define classes (Classes), structs (Structs), interfaces (Interfaces), enums (Enums), and delegates (Delegates). Los tipos de miembros permitidos en una declaración de tipo dependen del formulario de la declaración de tipos.The kinds of members permitted in a type declaration depend on the form of the type declaration. Por ejemplo, las declaraciones de clase pueden contener declaraciones de constantes (constantes), campos (campos), métodos (métodos), propiedades (propiedades), eventos (eventos), indizadores (indizadores). operadores (operadores), constructores de instancias (constructores de instancias), constructores estáticos (constructores estáticos), destructores (destructores) y tipos anidados (tipos anidados).For instance, class declarations can contain declarations for constants (Constants), fields (Fields), methods (Methods), properties (Properties), events (Events), indexers (Indexers), operators (Operators), instance constructors (Instance constructors), static constructors (Static constructors), destructors (Destructors), and nested types (Nested types).

Una declaración define un nombre en el espacio de declaración al que pertenece la declaración.A declaration defines a name in the declaration space to which the declaration belongs. A excepción de los miembros sobrecargados (firmas y sobrecarga), es un error en tiempo de compilación tener dos o más declaraciones que introducen miembros con el mismo nombre en un espacio de declaración.Except for overloaded members (Signatures and overloading), it is a compile-time error to have two or more declarations that introduce members with the same name in a declaration space. Nunca es posible que un espacio de declaración contenga distintos tipos de miembros con el mismo nombre.It is never possible for a declaration space to contain different kinds of members with the same name. Por ejemplo, un espacio de declaración nunca puede contener un campo y un método con el mismo nombre.For example, a declaration space can never contain a field and a method by the same name.

Hay varios tipos diferentes de espacios de declaración, como se describe a continuación.There are several different types of declaration spaces, as described in the following.

  • Dentro de todos los archivos de código fuente de un programa, namespace_member_declarations sin namespace_declaration envolventes son miembros de un único espacio de declaración combinado denominado espacio de declaración global.Within all source files of a program, namespace_member_declarations with no enclosing namespace_declaration are members of a single combined declaration space called the global declaration space.
  • Dentro de todos los archivos de código fuente de un programa, namespace_member_declarations dentro de namespace_declarations que tienen el mismo nombre de espacio de nombres completo son miembros de un solo espacio de declaración combinado.Within all source files of a program, namespace_member_declarations within namespace_declarations that have the same fully qualified namespace name are members of a single combined declaration space.
  • Cada declaración de clase, struct o interfaz crea un nuevo espacio de declaración.Each class, struct, or interface declaration creates a new declaration space. Los nombres se introducen en este espacio de declaración a través de class_member_declarations, struct_member_declarations, interface_member_declarations o type_parameters.Names are introduced into this declaration space through class_member_declarations, struct_member_declarations, interface_member_declarations, or type_parameters. A excepción de las declaraciones de constructor de instancia sobrecargadas y las declaraciones de constructor estático, una clase o struct no puede contener una declaración de miembro con el mismo nombre que la clase o la estructura.Except for overloaded instance constructor declarations and static constructor declarations, a class or struct cannot contain a member declaration with the same name as the class or struct. Una clase, estructura o interfaz permite la declaración de métodos sobrecargados e indexadores.A class, struct, or interface permits the declaration of overloaded methods and indexers. Además, una clase o struct permite la declaración de constructores de instancia sobrecargados y operadores.Furthermore, a class or struct permits the declaration of overloaded instance constructors and operators. Por ejemplo, una clase, un struct o una interfaz pueden contener varias declaraciones de método con el mismo nombre, siempre que estas declaraciones de método difieran en su firma (firmas y sobrecarga).For example, a class, struct, or interface may contain multiple method declarations with the same name, provided these method declarations differ in their signature (Signatures and overloading). Tenga en cuenta que las clases base no contribuyen al espacio de declaración de una clase, y las interfaces base no contribuyen al espacio de declaración de una interfaz.Note that base classes do not contribute to the declaration space of a class, and base interfaces do not contribute to the declaration space of an interface. Por lo tanto, una clase derivada o una interfaz pueden declarar un miembro con el mismo nombre que un miembro heredado.Thus, a derived class or interface is allowed to declare a member with the same name as an inherited member. Este miembro se dice que oculta el miembro heredado.Such a member is said to hide the inherited member.
  • Cada declaración de delegado crea un nuevo espacio de declaración.Each delegate declaration creates a new declaration space. Los nombres se introducen en este espacio de declaración a través de los parámetros formales (fixed_parameters y parameter_arrays) y type_parameters.Names are introduced into this declaration space through formal parameters (fixed_parameters and parameter_arrays) and type_parameters.
  • Cada declaración de enumeración crea un nuevo espacio de declaración.Each enumeration declaration creates a new declaration space. Los nombres se introducen en este espacio de declaración a través de enum_member_declarations.Names are introduced into this declaration space through enum_member_declarations.
  • Cada declaración de método, declaración de indexador, declaración de operador, declaración de constructor de instancia y función anónima crea un nuevo espacio de declaración denominado espacio de declaración de variable local.Each method declaration, indexer declaration, operator declaration, instance constructor declaration and anonymous function creates a new declaration space called a local variable declaration space. Los nombres se introducen en este espacio de declaración a través de los parámetros formales (fixed_parameters y parameter_arrays) y type_parameters.Names are introduced into this declaration space through formal parameters (fixed_parameters and parameter_arrays) and type_parameters. El cuerpo del miembro de función o de la función anónima, si existe, se considera anidado dentro del espacio de declaración de la variable local.The body of the function member or anonymous function, if any, is considered to be nested within the local variable declaration space. Es un error que un espacio de declaración de variable local y un espacio de declaración de variable local anidada contengan elementos con el mismo nombre.It is an error for a local variable declaration space and a nested local variable declaration space to contain elements with the same name. Por lo tanto, dentro de un espacio de declaración anidado no es posible declarar una variable o constante local con el mismo nombre que una variable o constante local en un espacio de declaración de inclusión.Thus, within a nested declaration space it is not possible to declare a local variable or constant with the same name as a local variable or constant in an enclosing declaration space. Es posible que dos espacios de declaración contengan elementos con el mismo nombre siempre y cuando ningún espacio de declaración contenga el otro.It is possible for two declaration spaces to contain elements with the same name as long as neither declaration space contains the other.
  • Cada bloque o switch_block , así como una instrucción for, foreach y using , crea un espacio de declaración de variable local para las variables locales y las constantes locales.Each block or switch_block , as well as a for, foreach and using statement, creates a local variable declaration space for local variables and local constants . Los nombres se introducen en este espacio de declaración a través de local_variable_declarations y local_constant_declarations.Names are introduced into this declaration space through local_variable_declarations and local_constant_declarations. Tenga en cuenta que los bloques que se producen como o dentro del cuerpo de un miembro de función o de una función anónima están anidados dentro del espacio de declaración de variable local declarado por esas funciones para sus parámetros.Note that blocks that occur as or within the body of a function member or anonymous function are nested within the local variable declaration space declared by those functions for their parameters. Por lo tanto, es un error tener, por ejemplo, un método con una variable local y un parámetro con el mismo nombre.Thus it is an error to have e.g. a method with a local variable and a parameter of the same name.
  • Cada bloque o switch_block crea un espacio de declaración independiente para las etiquetas.Each block or switch_block creates a separate declaration space for labels. Los nombres se introducen en este espacio de declaración a través de labeled_statements y se hace referencia a los nombres a través de goto_statements.Names are introduced into this declaration space through labeled_statements, and the names are referenced through goto_statements. El espacio de declaración de etiqueta de un bloque incluye cualquier bloque anidado.The label declaration space of a block includes any nested blocks. Por lo tanto, dentro de un bloque anidado no es posible declarar una etiqueta con el mismo nombre que una etiqueta en un bloque de inclusión.Thus, within a nested block it is not possible to declare a label with the same name as a label in an enclosing block.

El orden textual en el que se declaran los nombres no suele ser significativo.The textual order in which names are declared is generally of no significance. En concreto, el orden textual no es significativo para la declaración y el uso de espacios de nombres, constantes, métodos, propiedades, eventos, indizadores, operadores, constructores de instancias, destructores, constructores estáticos y tipos.In particular, textual order is not significant for the declaration and use of namespaces, constants, methods, properties, events, indexers, operators, instance constructors, destructors, static constructors, and types. El orden de declaración es significativo de las siguientes maneras:Declaration order is significant in the following ways:

  • El orden de declaración de las declaraciones de campo y las declaraciones de variables locales determina el orden en que se ejecutan sus inicializadores (si existen).Declaration order for field declarations and local variable declarations determines the order in which their initializers (if any) are executed.
  • Las variables locales deben definirse antes de que se usen (ámbitos).Local variables must be defined before they are used (Scopes).
  • El orden de declaración para las declaraciones de miembros de enumeración (miembros de enumeración) es importante cuando se omiten los valores de constant_expression .Declaration order for enum member declarations (Enum members) is significant when constant_expression values are omitted.

El espacio de declaración de un espacio de nombres es "Open Terminated" y dos declaraciones de espacios de nombres con el mismo nombre completo contribuyen al mismo espacio de declaración.The declaration space of a namespace is "open ended", and two namespace declarations with the same fully qualified name contribute to the same declaration space. Por ejemploFor example

namespace Megacorp.Data
{
    class Customer
    {
        ...
    }
}

namespace Megacorp.Data
{
    class Order
    {
        ...
    }
}

Las dos declaraciones de espacio de nombres anteriores contribuyen al mismo espacio de declaración; en este caso, se declaran dos clases con los nombres completos Megacorp.Data.Customer y Megacorp.Data.Order.The two namespace declarations above contribute to the same declaration space, in this case declaring two classes with the fully qualified names Megacorp.Data.Customer and Megacorp.Data.Order. Dado que las dos declaraciones contribuyen al mismo espacio de declaración, habría producido un error en tiempo de compilación si cada una de ellas contenía una declaración de una clase con el mismo nombre.Because the two declarations contribute to the same declaration space, it would have caused a compile-time error if each contained a declaration of a class with the same name.

Tal y como se especificó anteriormente, el espacio de declaración de un bloque incluye cualquier bloque anidado.As specified above, the declaration space of a block includes any nested blocks. Por lo tanto, en el ejemplo siguiente, los métodos F y G producen un error en tiempo de compilación porque el nombre i se declara en el bloque exterior y no se puede volver a declarar en el bloque interno.Thus, in the following example, the F and G methods result in a compile-time error because the name i is declared in the outer block and cannot be redeclared in the inner block. Sin embargo, los métodos H y I son válidos, ya que los dos @no__t 2 se declaran en bloques independientes no anidados.However, the H and I methods are valid since the two i's are declared in separate non-nested blocks.

class A
{
    void F() {
        int i = 0;
        if (true) {
            int i = 1;            
        }
    }

    void G() {
        if (true) {
            int i = 0;
        }
        int i = 1;                
    }

    void H() {
        if (true) {
            int i = 0;
        }
        if (true) {
            int i = 1;
        }
    }

    void I() {
        for (int i = 0; i < 10; i++)
            H();
        for (int i = 0; i < 10; i++)
            H();
    }
}

MiembrosMembers

Los espacios de nombres y lostipos tienen miembros.Namespaces and types have members. Los miembros de una entidad están disponibles con carácter general a través del uso de un nombre completo que empieza por una referencia a la entidad, seguido de un token ".", seguido del nombre del miembro.The members of an entity are generally available through the use of a qualified name that starts with a reference to the entity, followed by a "." token, followed by the name of the member.

Los miembros de un tipo se declaran en la declaración de tipos o se heredan de la clase base del tipo.Members of a type are either declared in the type declaration or inherited from the base class of the type. Cuando un tipo hereda de una clase base, todos los miembros de la clase base, excepto los constructores de instancia, destructores y constructores estáticos, se convierten en miembros del tipo derivado.When a type inherits from a base class, all members of the base class, except instance constructors, destructors and static constructors, become members of the derived type. La accesibilidad declarada de un miembro de clase base no controla si el miembro se hereda (la herencia se extiende a cualquier miembro que no sea un constructor de instancia, un constructor estático o un destructor).The declared accessibility of a base class member does not control whether the member is inherited—inheritance extends to any member that isn't an instance constructor, static constructor, or destructor. Sin embargo, es posible que no se pueda obtener acceso a un miembro heredado en un tipo derivado, ya sea debido a su accesibilidad declarada (accesibilidad declarada) o porque está oculta por una declaración en el propio tipo (ocultando a travésde la herencia).However, an inherited member may not be accessible in a derived type, either because of its declared accessibility (Declared accessibility) or because it is hidden by a declaration in the type itself (Hiding through inheritance).

Miembros de espacio de nombresNamespace members

Los espacios de nombres y los tipos que no tienen ningún espacio de nombres envolvente son miembros del espacio de nombres global.Namespaces and types that have no enclosing namespace are members of the global namespace. Se corresponde directamente con los nombres declarados en el espacio de declaración global.This corresponds directly to the names declared in the global declaration space.

Los espacios de nombres y los tipos declarados dentro de un espacio de nombres son miembros de ese espacio de nombres.Namespaces and types declared within a namespace are members of that namespace. Esto corresponde directamente a los nombres declarados en el espacio de declaración del espacio de nombres.This corresponds directly to the names declared in the declaration space of the namespace.

Los espacios de nombres no tienen restricciones de acceso.Namespaces have no access restrictions. No es posible declarar espacios de nombres privados, protegidos o internos, y los nombres de los espacios de nombres siempre son accesibles públicamente.It is not possible to declare private, protected, or internal namespaces, and namespace names are always publicly accessible.

Miembros de structStruct members

Los miembros de un struct son los miembros declarados en la estructura y los miembros heredados de la clase base directa de la estructura System.ValueType y la clase base indirecta object.The members of a struct are the members declared in the struct and the members inherited from the struct's direct base class System.ValueType and the indirect base class object.

Los miembros de un tipo simple se corresponden directamente con los miembros del tipo de struct con alias del tipo simple:The members of a simple type correspond directly to the members of the struct type aliased by the simple type:

  • Los miembros de sbyte son los miembros del struct System.SByte.The members of sbyte are the members of the System.SByte struct.
  • Los miembros de byte son los miembros del struct System.Byte.The members of byte are the members of the System.Byte struct.
  • Los miembros de short son los miembros del struct System.Int16.The members of short are the members of the System.Int16 struct.
  • Los miembros de ushort son los miembros del struct System.UInt16.The members of ushort are the members of the System.UInt16 struct.
  • Los miembros de int son los miembros del struct System.Int32.The members of int are the members of the System.Int32 struct.
  • Los miembros de uint son los miembros del struct System.UInt32.The members of uint are the members of the System.UInt32 struct.
  • Los miembros de long son los miembros del struct System.Int64.The members of long are the members of the System.Int64 struct.
  • Los miembros de ulong son los miembros del struct System.UInt64.The members of ulong are the members of the System.UInt64 struct.
  • Los miembros de char son los miembros del struct System.Char.The members of char are the members of the System.Char struct.
  • Los miembros de float son los miembros del struct System.Single.The members of float are the members of the System.Single struct.
  • Los miembros de double son los miembros del struct System.Double.The members of double are the members of the System.Double struct.
  • Los miembros de decimal son los miembros del struct System.Decimal.The members of decimal are the members of the System.Decimal struct.
  • Los miembros de bool son los miembros del struct System.Boolean.The members of bool are the members of the System.Boolean struct.

Miembros de enumeraciónEnumeration members

Los miembros de una enumeración son las constantes declaradas en la enumeración y los miembros heredados de la clase base directa de la enumeración System.Enum y las clases base indirectas System.ValueType y object.The members of an enumeration are the constants declared in the enumeration and the members inherited from the enumeration's direct base class System.Enum and the indirect base classes System.ValueType and object.

Miembros de la claseClass members

Los miembros de una clase son los miembros declarados en la clase y los miembros heredados de la clase base (excepto para la clase object que no tiene ninguna clase base).The members of a class are the members declared in the class and the members inherited from the base class (except for class object which has no base class). Los miembros heredados de la clase base incluyen las constantes, campos, métodos, propiedades, eventos, indizadores, operadores y tipos de la clase base, pero no los constructores de instancias, destructores y constructores estáticos de la clase base.The members inherited from the base class include the constants, fields, methods, properties, events, indexers, operators, and types of the base class, but not the instance constructors, destructors and static constructors of the base class. Los miembros de clase base se heredan sin tener en cuenta su accesibilidad.Base class members are inherited without regard to their accessibility.

Una declaración de clase puede contener declaraciones de constantes, campos, métodos, propiedades, eventos, indizadores, operadores, constructores de instancias, destructores, constructores estáticos y tipos.A class declaration may contain declarations of constants, fields, methods, properties, events, indexers, operators, instance constructors, destructors, static constructors and types.

Los miembros de object y string se corresponden directamente con los miembros de los tipos de clase a los que se les ha contorno:The members of object and string correspond directly to the members of the class types they alias:

  • Los miembros de object son los miembros de la clase System.Object.The members of object are the members of the System.Object class.
  • Los miembros de string son los miembros de la clase System.String.The members of string are the members of the System.String class.

Miembros de interfazInterface members

Los miembros de una interfaz son los miembros declarados en la interfaz y en todas las interfaces base de la interfaz.The members of an interface are the members declared in the interface and in all base interfaces of the interface. Los miembros de la clase object no son, estrictamente hablando, miembros de cualquier interfaz (miembros de lainterfaz).The members in class object are not, strictly speaking, members of any interface (Interface members). Sin embargo, los miembros de la clase object están disponibles a través de la búsqueda de miembros en cualquier tipo de interfaz (búsqueda de miembros).However, the members in class object are available via member lookup in any interface type (Member lookup).

Miembros de matrizArray members

Los miembros de una matriz son los miembros heredados de la clase System.Array.The members of an array are the members inherited from class System.Array.

Miembros de delegadoDelegate members

Los miembros de un delegado son los miembros heredados de la clase System.Delegate.The members of a delegate are the members inherited from class System.Delegate.

Acceso a miembrosMember access

Las declaraciones de miembros permiten el control sobre el acceso a miembros.Declarations of members allow control over member access. La accesibilidad de un miembro se establece mediante la accesibilidad declarada (accesibilidad declarada) del miembro combinado con la accesibilidad del tipo contenedor inmediato, si existe.The accessibility of a member is established by the declared accessibility (Declared accessibility) of the member combined with the accessibility of the immediately containing type, if any.

Cuando se permite el acceso a un miembro determinado, se dice que el miembro es accesible.When access to a particular member is allowed, the member is said to be accessible. Por el contrario, cuando no se permite el acceso a un miembro determinado, se dice que el miembro no es accesible.Conversely, when access to a particular member is disallowed, the member is said to be inaccessible. Se permite el acceso a un miembro cuando la ubicación textual en la que tiene lugar el acceso se incluye en el dominio de accesibilidad (dominios de accesibilidad) del miembro.Access to a member is permitted when the textual location in which the access takes place is included in the accessibility domain (Accessibility domains) of the member.

Accesibilidad declaradaDeclared accessibility

La accesibilidad declarada de un miembro puede ser una de las siguientes:The declared accessibility of a member can be one of the following:

  • Público, que se selecciona mediante la inclusión de un modificador public en la declaración de miembro.Public, which is selected by including a public modifier in the member declaration. El significado intuitivo de public es "acceso no limitado".The intuitive meaning of public is "access not limited".
  • Protected, que se selecciona mediante la inclusión de un modificador protected en la declaración de miembro.Protected, which is selected by including a protected modifier in the member declaration. El significado intuitivo de protected es el acceso limitado a la clase contenedora o a los tipos derivados de la clase contenedora.The intuitive meaning of protected is "access limited to the containing class or types derived from the containing class".
  • Internal, que se selecciona mediante la inclusión de un modificador internal en la declaración de miembro.Internal, which is selected by including an internal modifier in the member declaration. El significado intuitivo de internal es "acceso limitado a este programa".The intuitive meaning of internal is "access limited to this program".
  • Protected internal (es decir, Protected o Internal), que se selecciona mediante la inclusión de protected y un modificador internal en la declaración de miembro.Protected internal (meaning protected or internal), which is selected by including both a protected and an internal modifier in the member declaration. El significado intuitivo de protected internal es "acceso limitado a este programa o tipos derivados de la clase contenedora".The intuitive meaning of protected internal is "access limited to this program or types derived from the containing class".
  • Private, que se selecciona mediante la inclusión de un modificador private en la declaración de miembro.Private, which is selected by including a private modifier in the member declaration. El significado intuitivo de private es "acceso limitado al tipo contenedor".The intuitive meaning of private is "access limited to the containing type".

Dependiendo del contexto en el que tenga lugar una declaración de miembro, solo se permiten determinados tipos de accesibilidad declarada.Depending on the context in which a member declaration takes place, only certain types of declared accessibility are permitted. Además, cuando una declaración de miembro no incluye modificadores de acceso, el contexto en el que se produce la declaración determina la accesibilidad declarada predeterminada.Furthermore, when a member declaration does not include any access modifiers, the context in which the declaration takes place determines the default declared accessibility.

  • Los espacios de nombres tienen implícitamente la accesibilidad public.Namespaces implicitly have public declared accessibility. No se permiten modificadores de acceso en las declaraciones de espacio de nombres.No access modifiers are allowed on namespace declarations.
  • Los tipos declarados en unidades de compilación o espacios de nombres pueden tener @no__t la accesibilidad declarada como 0 o internal y tienen como valor predeterminado la accesibilidad declarada @no__t 2.Types declared in compilation units or namespaces can have public or internal declared accessibility and default to internal declared accessibility.
  • Los miembros de clase pueden tener cualquiera de los cinco tipos de accesibilidad declarada y su valor predeterminado es private, que es una accesibilidad declarada.Class members can have any of the five kinds of declared accessibility and default to private declared accessibility. (Tenga en cuenta que un tipo declarado como miembro de una clase puede tener cualquiera de los cinco tipos de accesibilidad declarada, mientras que un tipo declarado como miembro de un espacio de nombres solo puede tener la accesibilidad declarada public o internal).(Note that a type declared as a member of a class can have any of the five kinds of declared accessibility, whereas a type declared as a member of a namespace can have only public or internal declared accessibility.)
  • Los miembros de struct pueden tener la accesibilidad declarada public, internal o private y de forma predeterminada a private, ya que los Structs están sellados implícitamente.Struct members can have public, internal, or private declared accessibility and default to private declared accessibility because structs are implicitly sealed. Los miembros de estructura introducidos en un struct (es decir, no heredados por ese struct) no pueden tener accesibilidad declarada protected o protected internal.Struct members introduced in a struct (that is, not inherited by that struct) cannot have protected or protected internal declared accessibility. (Tenga en cuenta que un tipo declarado como miembro de un struct puede tener la accesibilidad declarada public, internal o private, mientras que un tipo declarado como miembro de un espacio de nombres solo puede tener la accesibilidad declarada public o internal).(Note that a type declared as a member of a struct can have public, internal, or private declared accessibility, whereas a type declared as a member of a namespace can have only public or internal declared accessibility.)
  • Los miembros de interfaz tienen implícitamente la accesibilidad public.Interface members implicitly have public declared accessibility. No se permiten modificadores de acceso en las declaraciones de miembros de interfaz.No access modifiers are allowed on interface member declarations.
  • Los miembros de enumeración tienen implícitamente la accesibilidad declarada public.Enumeration members implicitly have public declared accessibility. No se permiten modificadores de acceso en las declaraciones de miembros de enumeración.No access modifiers are allowed on enumeration member declarations.

Dominios de accesibilidadAccessibility domains

El dominio de accesibilidad de un miembro se compone de las secciones (posiblemente disjuntos) del texto del programa en el que se permite el acceso al miembro.The accessibility domain of a member consists of the (possibly disjoint) sections of program text in which access to the member is permitted. A efectos de definir el dominio de accesibilidad de un miembro, se dice que un miembro es de nivel superior si no se declara dentro de un tipo, y se dice que un miembro está anidado si se declara dentro de otro tipo.For purposes of defining the accessibility domain of a member, a member is said to be top-level if it is not declared within a type, and a member is said to be nested if it is declared within another type. Además, el texto del programa de un programa se define como todo el texto del programa contenido en todos los archivos de código fuente del programa, y el texto del programa de un tipo se define como todo el texto del programa contenido en el type_declarations de ese tipo (incluido, posiblemente, los tipos que están anidados dentro del tipo).Furthermore, the program text of a program is defined as all program text contained in all source files of the program, and the program text of a type is defined as all program text contained in the type_declarations of that type (including, possibly, types that are nested within the type).

El dominio de accesibilidad de un tipo predefinido (como object, int o double) es ilimitado.The accessibility domain of a predefined type (such as object, int, or double) is unlimited.

El dominio de accesibilidad de un tipo sin enlazar de nivel superior T (tipos enlazados y sin enlazar) que se declara en un programa P se define de la manera siguiente:The accessibility domain of a top-level unbound type T (Bound and unbound types) that is declared in a program P is defined as follows:

  • Si la accesibilidad declarada de T es public, el dominio de accesibilidad de T es el texto de programa de P y cualquier programa que haga referencia a P.If the declared accessibility of T is public, the accessibility domain of T is the program text of P and any program that references P.
  • Si la accesibilidad declarada de T es internal, el dominio de accesibilidad de T es el texto de programa de P.If the declared accessibility of T is internal, the accessibility domain of T is the program text of P.

A partir de estas definiciones, sigue que el dominio de accesibilidad de un tipo sin enlazar de nivel superior siempre es al menos el texto del programa del programa en el que se declara ese tipo.From these definitions it follows that the accessibility domain of a top-level unbound type is always at least the program text of the program in which that type is declared.

El dominio de accesibilidad de un tipo construido T<A1, ..., An> es la intersección del dominio de accesibilidad del tipo genérico sin enlazar T y los dominios de accesibilidad de los argumentos de tipo A1, ..., An.The accessibility domain for a constructed type T<A1, ..., An> is the intersection of the accessibility domain of the unbound generic type T and the accessibility domains of the type arguments A1, ..., An.

El dominio de accesibilidad de un miembro anidado M declarado en un tipo T dentro de un programa P se define de la manera siguiente (teniendo en cuenta que M puede ser un tipo):The accessibility domain of a nested member M declared in a type T within a program P is defined as follows (noting that M itself may possibly be a type):

  • Si la accesibilidad declarada de M es public, el dominio de accesibilidad de M es el dominio de accesibilidad de T.If the declared accessibility of M is public, the accessibility domain of M is the accessibility domain of T.
  • Si la accesibilidad declarada de M es protected internal, permita que D sea la Unión del texto del programa de P y el texto del programa de cualquier tipo derivado de T, que se declara fuera de P.If the declared accessibility of M is protected internal, let D be the union of the program text of P and the program text of any type derived from T, which is declared outside P. El dominio de accesibilidad de M es la intersección del dominio de accesibilidad de T con D.The accessibility domain of M is the intersection of the accessibility domain of T with D.
  • Si la accesibilidad declarada de M es protected, permita que D sea la Unión del texto del programa de T y el texto del programa de cualquier tipo derivado de T.If the declared accessibility of M is protected, let D be the union of the program text of T and the program text of any type derived from T. El dominio de accesibilidad de M es la intersección del dominio de accesibilidad de T con D.The accessibility domain of M is the intersection of the accessibility domain of T with D.
  • Si la accesibilidad declarada de M es internal, el dominio de accesibilidad de M es la intersección del dominio de accesibilidad de T con el texto de programa de P.If the declared accessibility of M is internal, the accessibility domain of M is the intersection of the accessibility domain of T with the program text of P.
  • Si la accesibilidad declarada de M es private, el dominio de accesibilidad de M es el texto de programa de T.If the declared accessibility of M is private, the accessibility domain of M is the program text of T.

A partir de estas definiciones, sigue que el dominio de accesibilidad de un miembro anidado siempre es al menos el texto del programa del tipo en el que se declara el miembro.From these definitions it follows that the accessibility domain of a nested member is always at least the program text of the type in which the member is declared. Además, sigue que el dominio de accesibilidad de un miembro nunca es más inclusivo que el dominio de accesibilidad del tipo en el que se declara el miembro.Furthermore, it follows that the accessibility domain of a member is never more inclusive than the accessibility domain of the type in which the member is declared.

En términos intuitivos, cuando se tiene acceso a un tipo o miembro M, se evalúan los pasos siguientes para asegurarse de que se permite el acceso:In intuitive terms, when a type or member M is accessed, the following steps are evaluated to ensure that the access is permitted:

  • En primer lugar, si M se declara dentro de un tipo (en lugar de una unidad de compilación o un espacio de nombres), se produce un error en tiempo de compilación si ese tipo no es accesible.First, if M is declared within a type (as opposed to a compilation unit or a namespace), a compile-time error occurs if that type is not accessible.
  • A continuación, si M es public, se permite el acceso.Then, if M is public, the access is permitted.
  • De lo contrario, si M es protected internal, se permite el acceso si se produce en el programa en el que se declara M, o bien, si se produce dentro de una clase derivada de la clase en la que se declara M y tiene lugar a través del tipo de clase derivada (protegido). acceso para los miembros de instancia).Otherwise, if M is protected internal, the access is permitted if it occurs within the program in which M is declared, or if it occurs within a class derived from the class in which M is declared and takes place through the derived class type (Protected access for instance members).
  • De lo contrario, si M es protected, se permite el acceso si se produce dentro de la clase en la que se declara M, o bien, si se produce en una clase derivada de la clase en la que se declara M y tiene lugar a través del tipo de clase derivada (protegido). acceso para los miembros de instancia).Otherwise, if M is protected, the access is permitted if it occurs within the class in which M is declared, or if it occurs within a class derived from the class in which M is declared and takes place through the derived class type (Protected access for instance members).
  • De lo contrario, si M es internal, se permite el acceso si se produce en el programa en el que se declara M.Otherwise, if M is internal, the access is permitted if it occurs within the program in which M is declared.
  • De lo contrario, si M es private, se permite el acceso si se produce en el tipo en el que se declara M.Otherwise, if M is private, the access is permitted if it occurs within the type in which M is declared.
  • De lo contrario, no se puede obtener acceso al tipo o miembro y se produce un error en tiempo de compilación.Otherwise, the type or member is inaccessible, and a compile-time error occurs.

En el ejemploIn the example

public class A
{
    public static int X;
    internal static int Y;
    private static int Z;
}

internal class B
{
    public static int X;
    internal static int Y;
    private static int Z;

    public class C
    {
        public static int X;
        internal static int Y;
        private static int Z;
    }

    private class D
    {
        public static int X;
        internal static int Y;
        private static int Z;
    }
}

las clases y los miembros tienen los siguientes dominios de accesibilidad:the classes and members have the following accessibility domains:

  • El dominio de accesibilidad de A y A.X es ilimitado.The accessibility domain of A and A.X is unlimited.
  • El dominio de accesibilidad de A.Y, B, B.X, B.Y, B.C, B.C.X y B.C.Y es el texto del programa que lo contiene.The accessibility domain of A.Y, B, B.X, B.Y, B.C, B.C.X, and B.C.Y is the program text of the containing program.
  • El dominio de accesibilidad de A.Z es el texto del programa de A.The accessibility domain of A.Z is the program text of A.
  • El dominio de accesibilidad de B.Z y B.D es el texto de programa de B, incluido el texto del programa de B.C y B.D.The accessibility domain of B.Z and B.D is the program text of B, including the program text of B.C and B.D.
  • El dominio de accesibilidad de B.C.Z es el texto del programa de B.C.The accessibility domain of B.C.Z is the program text of B.C.
  • El dominio de accesibilidad de B.D.X y B.D.Y es el texto de programa de B, incluido el texto del programa de B.C y B.D.The accessibility domain of B.D.X and B.D.Y is the program text of B, including the program text of B.C and B.D.
  • El dominio de accesibilidad de B.D.Z es el texto del programa de B.D.The accessibility domain of B.D.Z is the program text of B.D.

Como se muestra en el ejemplo, el dominio de accesibilidad de un miembro nunca es mayor que el de un tipo contenedor.As the example illustrates, the accessibility domain of a member is never larger than that of a containing type. Por ejemplo, aunque todos los miembros X tengan una accesibilidad declarada pública, todos salvo A.X tienen dominios de accesibilidad que están restringidos por un tipo contenedor.For example, even though all X members have public declared accessibility, all but A.X have accessibility domains that are constrained by a containing type.

Como se describe en miembros, todos los miembros de una clase base, excepto los constructores de instancias, destructores y constructores estáticos, los heredan los tipos derivados.As described in Members, all members of a base class, except for instance constructors, destructors and static constructors, are inherited by derived types. Esto incluye incluso miembros privados de una clase base.This includes even private members of a base class. Sin embargo, el dominio de accesibilidad de un miembro privado incluye solo el texto del programa del tipo en el que se declara el miembro.However, the accessibility domain of a private member includes only the program text of the type in which the member is declared. En el ejemploIn the example

class A
{
    int x;

    static void F(B b) {
        b.x = 1;        // Ok
    }
}

class B: A
{
    static void F(B b) {
        b.x = 1;        // Error, x not accessible
    }
}

la clase B hereda el miembro privado x de la clase A.the B class inherits the private member x from the A class. Dado que el miembro es privado, solo es accesible dentro del class_body de A.Because the member is private, it is only accessible within the class_body of A. Por lo tanto, el acceso a b.x se realiza correctamente en el método A.F, pero produce un error en el método B.F.Thus, the access to b.x succeeds in the A.F method, but fails in the B.F method.

Acceso protegido para miembros de instanciaProtected access for instance members

Cuando se tiene acceso a un miembro de instancia protected fuera del texto del programa de la clase en la que se declara, y cuando se tiene acceso a un miembro de instancia protected internal fuera del texto del programa en el que se declara, el acceso debe realizarse dentro de una clase. declaración que se deriva de la clase en la que se declara.When a protected instance member is accessed outside the program text of the class in which it is declared, and when a protected internal instance member is accessed outside the program text of the program in which it is declared, the access must take place within a class declaration that derives from the class in which it is declared. Además, el acceso debe realizarse a través de una instancia de ese tipo de clase derivada o de un tipo de clase construido a partir de él.Furthermore, the access is required to take place through an instance of that derived class type or a class type constructed from it. Esta restricción evita que una clase derivada tenga acceso a miembros protegidos de otras clases derivadas, incluso cuando los miembros se heredan de la misma clase base.This restriction prevents one derived class from accessing protected members of other derived classes, even when the members are inherited from the same base class.

Permita que B sea una clase base que declare un miembro de instancia protegido M y deje que D sea una clase que derive de B.Let B be a base class that declares a protected instance member M, and let D be a class that derives from B. Dentro del class_body de D, el acceso a M puede adoptar uno de los siguientes formatos:Within the class_body of D, access to M can take one of the following forms:

  • Un type_name o primary_expression no calificado con el formato M.An unqualified type_name or primary_expression of the form M.
  • Un primary_expression con el formato E.M, siempre que el tipo de E sea T o una clase derivada de T, donde T es el tipo de clase D o un tipo de clase construido a partir de DA primary_expression of the form E.M, provided the type of E is T or a class derived from T, where T is the class type D, or a class type constructed from D
  • Primary_expression con el formato base.M.A primary_expression of the form base.M.

Además de estas formas de acceso, una clase derivada puede tener acceso a un constructor de instancia protegido de una clase base en un constructor_initializer (inicializadores de constructor).In addition to these forms of access, a derived class can access a protected instance constructor of a base class in a constructor_initializer (Constructor initializers).

En el ejemploIn the example

public class A
{
    protected int x;

    static void F(A a, B b) {
        a.x = 1;        // Ok
        b.x = 1;        // Ok
    }
}

public class B: A
{
    static void F(A a, B b) {
        a.x = 1;        // Error, must access through instance of B
        b.x = 1;        // Ok
    }
}

dentro de A, es posible tener acceso a x a través de instancias de A y B, ya que en cualquier caso el acceso se realiza a través de una instancia de A o una clase derivada de A.within A, it is possible to access x through instances of both A and B, since in either case the access takes place through an instance of A or a class derived from A. Sin embargo, en B, no es posible tener acceso a x a través de una instancia de A, ya que A no se deriva de B.However, within B, it is not possible to access x through an instance of A, since A does not derive from B.

En el ejemploIn the example

class C<T>
{
    protected T x;
}

class D<T>: C<T>
{
    static void F() {
        D<T> dt = new D<T>();
        D<int> di = new D<int>();
        D<string> ds = new D<string>();
        dt.x = default(T);
        di.x = 123;
        ds.x = "test";
    }
}

las tres asignaciones a x se permiten porque todas tienen lugar a través de instancias de tipos de clase construidas a partir del tipo genérico.the three assignments to x are permitted because they all take place through instances of class types constructed from the generic type.

Restricciones de accesibilidadAccessibility constraints

Varias construcciones del C# lenguaje requieren que un tipo sea al menos tan accesible como miembro u otro tipo.Several constructs in the C# language require a type to be at least as accessible as a member or another type. Se dice que un tipo T es al menos tan accesible como miembro o tipo M si el dominio de accesibilidad de T es un supraconjunto del dominio de accesibilidad de M.A type T is said to be at least as accessible as a member or type M if the accessibility domain of T is a superset of the accessibility domain of M. En otras palabras, T es al menos tan accesible como M si T es accesible en todos los contextos en los que se puede tener acceso a M.In other words, T is at least as accessible as M if T is accessible in all contexts in which M is accessible.

Existen las siguientes restricciones de accesibilidad:The following accessibility constraints exist:

  • La clase base directa de un tipo de clase debe ser al menos igual de accesible que el propio tipo de clase.The direct base class of a class type must be at least as accessible as the class type itself.
  • Las interfaces base explícitas de un tipo de interfaz deben ser al menos igual de accesibles que el propio tipo de interfaz.The explicit base interfaces of an interface type must be at least as accessible as the interface type itself.
  • El tipo de valor devuelto y los tipos de parámetros de un tipo de delegado deben ser al menos igual de accesibles que el propio tipo de delegado.The return type and parameter types of a delegate type must be at least as accessible as the delegate type itself.
  • El tipo de una constante debe ser al menos igual de accesible que la propia constante.The type of a constant must be at least as accessible as the constant itself.
  • El tipo de un campo debe ser al menos igual de accesible que el propio campo.The type of a field must be at least as accessible as the field itself.
  • El tipo de valor devuelto y los tipos de parámetros de un método deben ser al menos igual de accesibles que el propio método.The return type and parameter types of a method must be at least as accessible as the method itself.
  • El tipo de una propiedad debe ser al menos igual de accesible que la misma propiedad.The type of a property must be at least as accessible as the property itself.
  • El tipo de un evento debe ser al menos igual de accesible que el propio evento.The type of an event must be at least as accessible as the event itself.
  • Los tipos de parámetro y el tipo de un indexador deben ser al menos igual de accesibles que el propio indexador.The type and parameter types of an indexer must be at least as accessible as the indexer itself.
  • El tipo de valor devuelto y los tipos de parámetro de un operador deben ser al menos igual de accesibles que el propio operador.The return type and parameter types of an operator must be at least as accessible as the operator itself.
  • Los tipos de parámetro de un constructor de instancia deben ser al menos tan accesibles como el propio constructor de instancia.The parameter types of an instance constructor must be at least as accessible as the instance constructor itself.

En el ejemploIn the example

class A {...}

public class B: A {...}

la clase B produce un error en tiempo de compilación porque A no es al menos tan accesible como B.the B class results in a compile-time error because A is not at least as accessible as B.

Del mismo modo, en el ejemploLikewise, in the example

class A {...}

public class B
{
    A F() {...}

    internal A G() {...}

    public A H() {...}
}

el método H de B produce un error en tiempo de compilación porque el tipo de valor devuelto A no es al menos tan accesible como el método.the H method in B results in a compile-time error because the return type A is not at least as accessible as the method.

Firmas y sobrecargaSignatures and overloading

Los métodos, los constructores de instancia, los indizadores y los operadores se caracterizan por sus firmas:Methods, instance constructors, indexers, and operators are characterized by their signatures:

  • La firma de un método consta del nombre del método, el número de parámetros de tipo y el tipo y la clase (valor, referencia o salida) de cada uno de sus parámetros formales, que se considera en el orden de izquierda a derecha.The signature of a method consists of the name of the method, the number of type parameters and the type and kind (value, reference, or output) of each of its formal parameters, considered in the order left to right. Para estos propósitos, cualquier parámetro de tipo del método que se produce en el tipo de un parámetro formal se identifica no por su nombre, sino por su posición ordinal en la lista de argumentos de tipo del método.For these purposes, any type parameter of the method that occurs in the type of a formal parameter is identified not by its name, but by its ordinal position in the type argument list of the method. La firma de un método no incluye específicamente el tipo de valor devuelto, el modificador params que se puede especificar para el parámetro situado más a la derecha, ni las restricciones de parámetro de tipo opcional.The signature of a method specifically does not include the return type, the params modifier that may be specified for the right-most parameter, nor the optional type parameter constraints.
  • La firma de un constructor de instancia consta del tipo y el tipo (valor, referencia o salida) de cada uno de sus parámetros formales, considerados en el orden de izquierda a derecha.The signature of an instance constructor consists of the type and kind (value, reference, or output) of each of its formal parameters, considered in the order left to right. La firma de un constructor de instancia no incluye específicamente el modificador params que se puede especificar para el parámetro situado más a la derecha.The signature of an instance constructor specifically does not include the params modifier that may be specified for the right-most parameter.
  • La firma de un indexador consta del tipo de cada uno de sus parámetros formales, que se considera en el orden de izquierda a derecha.The signature of an indexer consists of the type of each of its formal parameters, considered in the order left to right. La firma de un indexador no incluye específicamente el tipo de elemento, ni incluye el modificador params que se puede especificar para el parámetro situado más a la derecha.The signature of an indexer specifically does not include the element type, nor does it include the params modifier that may be specified for the right-most parameter.
  • La firma de un operador consta del nombre del operador y el tipo de cada uno de sus parámetros formales, considerados en el orden de izquierda a derecha.The signature of an operator consists of the name of the operator and the type of each of its formal parameters, considered in the order left to right. La firma de un operador no incluye específicamente el tipo de resultado.The signature of an operator specifically does not include the result type.

Las firmas son el mecanismo de habilitación para la sobrecarga de miembros en clases, Structs e interfaces:Signatures are the enabling mechanism for overloading of members in classes, structs, and interfaces:

  • La sobrecarga de métodos permite a una clase, estructura o interfaz declarar varios métodos con el mismo nombre, siempre que sus firmas sean únicas dentro de esa clase, estructura o interfaz.Overloading of methods permits a class, struct, or interface to declare multiple methods with the same name, provided their signatures are unique within that class, struct, or interface.
  • La sobrecarga de constructores de instancia permite a una clase o struct declarar varios constructores de instancia, siempre que sus firmas sean únicas dentro de esa clase o estructura.Overloading of instance constructors permits a class or struct to declare multiple instance constructors, provided their signatures are unique within that class or struct.
  • La sobrecarga de indexadores permite a una clase, estructura o interfaz declarar varios indexadores, siempre que sus firmas sean únicas dentro de esa clase, estructura o interfaz.Overloading of indexers permits a class, struct, or interface to declare multiple indexers, provided their signatures are unique within that class, struct, or interface.
  • La sobrecarga de los operadores permite a una clase o struct declarar varios operadores con el mismo nombre, siempre que sus firmas sean únicas dentro de esa clase o estructura.Overloading of operators permits a class or struct to declare multiple operators with the same name, provided their signatures are unique within that class or struct.

Aunque los modificadores de parámetro out y ref se consideran parte de una firma, los miembros declarados en un tipo único no pueden diferir en la firma únicamente en ref y out.Although out and ref parameter modifiers are considered part of a signature, members declared in a single type cannot differ in signature solely by ref and out. Se produce un error en tiempo de compilación si dos miembros se declaran en el mismo tipo con firmas que serían iguales si se cambiaran todos los parámetros de ambos métodos con modificadores out a los modificadores ref.A compile-time error occurs if two members are declared in the same type with signatures that would be the same if all parameters in both methods with out modifiers were changed to ref modifiers. Para otros propósitos de coincidencia de la firma (por ejemplo, ocultar o reemplazar), ref y out se consideran parte de la firma y no coinciden entre sí.For other purposes of signature matching (e.g., hiding or overriding), ref and out are considered part of the signature and do not match each other. (Esta restricción consiste en permitir C# que los programas se traduzcan fácilmente para ejecutarse en el Common Language Infrastructure (CLI), que no proporciona una manera de definir métodos que difieren únicamente en ref y out).(This restriction is to allow C#  programs to be easily translated to run on the Common Language Infrastructure (CLI), which does not provide a way to define methods that differ solely in ref and out.)

En el caso de las firmas, los tipos object y dynamic se consideran iguales.For the purposes of signatures, the types object and dynamic are considered the same. Los miembros declarados en un tipo único pueden, por tanto, no diferir en la firma únicamente en object y dynamic.Members declared in a single type can therefore not differ in signature solely by object and dynamic.

En el ejemplo siguiente se muestra un conjunto de declaraciones de método sobrecargado junto con sus firmas.The following example shows a set of overloaded method declarations along with their signatures.

interface ITest
{
    void F();                        // F()

    void F(int x);                   // F(int)

    void F(ref int x);               // F(ref int)

    void F(out int x);               // F(out int)      error

    void F(int x, int y);            // F(int, int)

    int F(string s);                 // F(string)

    int F(int x);                    // F(int)          error

    void F(string[] a);              // F(string[])

    void F(params string[] a);       // F(string[])     error
}

Tenga en cuenta que los modificadores de parámetro ref y out (parámetros de método) forman parte de una firma.Note that any ref and out parameter modifiers (Method parameters) are part of a signature. Por lo tanto, F(int) y F(ref int) son firmas únicas.Thus, F(int) and F(ref int) are unique signatures. Sin embargo, F(ref int) y F(out int) no se pueden declarar dentro de la misma interfaz porque las firmas difieren únicamente en ref y out.However, F(ref int) and F(out int) cannot be declared within the same interface because their signatures differ solely by ref and out. Además, tenga en cuenta que el tipo de valor devuelto y el modificador params no forman parte de una firma, por lo que no es posible sobrecargar únicamente en función del tipo de valor devuelto o de la inclusión o exclusión del modificador params.Also, note that the return type and the params modifier are not part of a signature, so it is not possible to overload solely based on return type or on the inclusion or exclusion of the params modifier. Como tal, las declaraciones de los métodos F(int) y F(params string[]) identificados anteriormente provocan un error en tiempo de compilación.As such, the declarations of the methods F(int) and F(params string[]) identified above result in a compile-time error.

ÁmbitosScopes

El ámbito de un nombre es la región del texto del programa en la que es posible hacer referencia a la entidad declarada por el nombre sin la calificación del nombre.The scope of a name is the region of program text within which it is possible to refer to the entity declared by the name without qualification of the name. Los ámbitos se pueden anidary un ámbito interno puede volver a declarar el significado de un nombre desde un ámbito externo (sin embargo, no se quita la restricción impuesta por las declaraciones que se encuentran dentro de un bloque anidado no es posible declarar una variable local con el el mismo nombre que una variable local en un bloque de inclusión).Scopes can be nested, and an inner scope may redeclare the meaning of a name from an outer scope (this does not, however, remove the restriction imposed by Declarations that within a nested block it is not possible to declare a local variable with the same name as a local variable in an enclosing block). A continuación, se dice que el nombre del ámbito externo está oculto en la región del texto del programa que abarca el ámbito interno y el acceso al nombre externo solo es posible mediante la calificación del nombre.The name from the outer scope is then said to be hidden in the region of program text covered by the inner scope, and access to the outer name is only possible by qualifying the name.

  • El ámbito de un miembro de espacio de nombres declarado por un namespace_member_declaration (miembros de espacio de nombres) sin ningún namespace_declaration envolvente es todo el texto del programa.The scope of a namespace member declared by a namespace_member_declaration (Namespace members) with no enclosing namespace_declaration is the entire program text.
  • El ámbito de un miembro de espacio de nombres declarado por un namespace_member_declaration dentro de un namespace_declaration cuyo nombre completo es N es el namespace_body de cada namespace_declaration cuyo el nombre completo es N o empieza por N, seguido de un punto.The scope of a namespace member declared by a namespace_member_declaration within a namespace_declaration whose fully qualified name is N is the namespace_body of every namespace_declaration whose fully qualified name is N or starts with N, followed by a period.
  • El ámbito del nombre definido por un extern_alias_directive se extiende a través de using_directives, global_attributes y namespace_member_declarations de su unidad de compilación o cuerpo de espacio de nombres que contiene inmediatamente.The scope of name defined by an extern_alias_directive extends over the using_directives, global_attributes and namespace_member_declarations of its immediately containing compilation unit or namespace body. Un extern_alias_directive no aporta ningún miembro nuevo al espacio de declaración subyacente.An extern_alias_directive does not contribute any new members to the underlying declaration space. En otras palabras, una extern_alias_directive no es transitiva, sino que solo afecta a la unidad de compilación o al cuerpo del espacio de nombres en el que se produce.In other words, an extern_alias_directive is not transitive, but, rather, affects only the compilation unit or namespace body in which it occurs.
  • El ámbito de un nombre definido o importado por una using_directive (mediante directivas) se extiende a través de los namespace_member_declarationde compilation_unit o namespace_body en los que using_directive se produce.The scope of a name defined or imported by a using_directive (Using directives) extends over the namespace_member_declarations of the compilation_unit or namespace_body in which the using_directive occurs. Una using_directive puede hacer que cero o más nombres de espacio de nombres, tipo o miembro estén disponibles en un compilation_unit o namespace_bodydeterminado, pero no contribuye a ningún miembro nuevo en el espacio de declaración subyacente.A using_directive may make zero or more namespace, type or member names available within a particular compilation_unit or namespace_body, but does not contribute any new members to the underlying declaration space. En otras palabras, un using_directive no es transitivo sino que solo afecta al compilation_unit o namespace_body en el que se produce.In other words, a using_directive is not transitive but rather affects only the compilation_unit or namespace_body in which it occurs.
  • El ámbito de un parámetro de tipo declarado por un type_parameter_list en un class_declaration (declaraciones de clase) es class_base, type_parameter_constraints_clauses y class_body de ese class_declaration.The scope of a type parameter declared by a type_parameter_list on a class_declaration (Class declarations) is the class_base, type_parameter_constraints_clauses, and class_body of that class_declaration.
  • El ámbito de un parámetro de tipo declarado por type_parameter_list en un struct_declaration (declaraciones de struct) es struct_interfaces, type_parameter_constraints_clauses y struct_body de esa struct_declaration.The scope of a type parameter declared by a type_parameter_list on a struct_declaration (Struct declarations) is the struct_interfaces, type_parameter_constraints_clauses, and struct_body of that struct_declaration.
  • El ámbito de un parámetro de tipo declarado por un type_parameter_list en un interface_declaration (declaraciones de interfaz) es interface_base, type_parameter_constraints_clauses y interface_body de ese interface_declaration.The scope of a type parameter declared by a type_parameter_list on an interface_declaration (Interface declarations) is the interface_base, type_parameter_constraints_clauses, and interface_body of that interface_declaration.
  • El ámbito de un parámetro de tipo declarado por un type_parameter_list en un delegate_declaration (declaraciones de delegado) es el tipo, formal_parameter_listy type_parameter_constraints_clause s de ese delegate_declaration.The scope of a type parameter declared by a type_parameter_list on a delegate_declaration (Delegate declarations) is the return_type, formal_parameter_list, and type_parameter_constraints_clauses of that delegate_declaration.
  • El ámbito de un miembro declarado por un class_member_declaration (cuerpo de clase) es el class_body en el que se produce la declaración.The scope of a member declared by a class_member_declaration (Class body) is the class_body in which the declaration occurs. Además, el ámbito de un miembro de clase se extiende hasta el class_body de las clases derivadas que se incluyen en el dominio de accesibilidad (dominios de accesibilidad) del miembro.In addition, the scope of a class member extends to the class_body of those derived classes that are included in the accessibility domain (Accessibility domains) of the member.
  • El ámbito de un miembro declarado por un struct_member_declaration (miembros de struct) es el struct_body en el que se produce la declaración.The scope of a member declared by a struct_member_declaration (Struct members) is the struct_body in which the declaration occurs.
  • El ámbito de un miembro declarado por un enum_member_declaration (enumerar miembros) es el enum_body en el que se produce la declaración.The scope of a member declared by an enum_member_declaration (Enum members) is the enum_body in which the declaration occurs.
  • El ámbito de un parámetro declarado en una method_declaration (métodos) es el method_body de ese method_declaration.The scope of a parameter declared in a method_declaration (Methods) is the method_body of that method_declaration.
  • El ámbito de un parámetro declarado en un indexer_declaration (indexadores) es el accessor_declarations de ese indexer_declaration.The scope of a parameter declared in an indexer_declaration (Indexers) is the accessor_declarations of that indexer_declaration.
  • El ámbito de un parámetro declarado en una operator_declaration (operadores) es el bloque de ese operator_declaration.The scope of a parameter declared in an operator_declaration (Operators) is the block of that operator_declaration.
  • El ámbito de un parámetro declarado en un constructor_declaration (constructores de instancia) es el constructor_initializer y el bloque de ese constructor_declaration.The scope of a parameter declared in a constructor_declaration (Instance constructors) is the constructor_initializer and block of that constructor_declaration.
  • El ámbito de un parámetro declarado en una lambda_expression (expresiones de función anónima) es el anonymous_function_body de ese lambda_expressionThe scope of a parameter declared in a lambda_expression (Anonymous function expressions) is the anonymous_function_body of that lambda_expression
  • El ámbito de un parámetro declarado en una anonymous_method_expression (expresiones de función anónima) es el bloque de ese anonymous_method_expression.The scope of a parameter declared in an anonymous_method_expression (Anonymous function expressions) is the block of that anonymous_method_expression.
  • El ámbito de una etiqueta declarada en un labeled_statement (instrucciones con etiqueta) es el bloque en el que se produce la declaración.The scope of a label declared in a labeled_statement (Labeled statements) is the block in which the declaration occurs.
  • El ámbito de una variable local declarada en un local_variable_declaration (declaraciones de variables locales) es el bloque en el que se produce la declaración.The scope of a local variable declared in a local_variable_declaration (Local variable declarations) is the block in which the declaration occurs.
  • El ámbito de una variable local declarada en un switch_block de una instrucción switch (la instrucción switch) es switch_block.The scope of a local variable declared in a switch_block of a switch statement (The switch statement) is the switch_block.
  • El ámbito de una variable local declarada en un for_initializer de una instrucción for (la instrucción for) es for_initializer, for_condition, for_iteratory la instrucción contenida del instrucción for.The scope of a local variable declared in a for_initializer of a for statement (The for statement) is the for_initializer, the for_condition, the for_iterator, and the contained statement of the for statement.
  • El ámbito de una constante local declarada en un local_constant_declaration (declaraciones de constantes locales) es el bloque en el que se produce la declaración.The scope of a local constant declared in a local_constant_declaration (Local constant declarations) is the block in which the declaration occurs. Es un error en tiempo de compilación hacer referencia a una constante local en una posición textual que precede a su constant_declarator.It is a compile-time error to refer to a local constant in a textual position that precedes its constant_declarator.
  • El ámbito de una variable declarada como parte de foreach_statement, using_statement, lock_statement o query_expression viene determinado por la expansión de la construcción especificada.The scope of a variable declared as part of a foreach_statement, using_statement, lock_statement or query_expression is determined by the expansion of the given construct.

Dentro del ámbito de un espacio de nombres, una clase, un struct o un miembro de enumeración, es posible hacer referencia al miembro en una posición textual que preceda a la declaración del miembro.Within the scope of a namespace, class, struct, or enumeration member it is possible to refer to the member in a textual position that precedes the declaration of the member. Por ejemploFor example

class A
{
    void F() {
        i = 1;
    }

    int i = 0;
}

Aquí, es válido para que F haga referencia a i antes de que se declare.Here, it is valid for F to refer to i before it is declared.

Dentro del ámbito de una variable local, se trata de un error en tiempo de compilación para hacer referencia a la variable local en una posición textual que precede a la local_variable_declarator de la variable local.Within the scope of a local variable, it is a compile-time error to refer to the local variable in a textual position that precedes the local_variable_declarator of the local variable. Por ejemploFor example

class A
{
    int i = 0;

    void F() {
        i = 1;                  // Error, use precedes declaration
        int i;
        i = 2;
    }

    void G() {
        int j = (j = 1);        // Valid
    }

    void H() {
        int a = 1, b = ++a;    // Valid
    }
}

En el método F anterior, la primera asignación a i no hace referencia específicamente al campo declarado en el ámbito externo.In the F method above, the first assignment to i specifically does not refer to the field declared in the outer scope. En su lugar, hace referencia a la variable local y produce un error en tiempo de compilación porque precede textualmente a la declaración de la variable.Rather, it refers to the local variable and it results in a compile-time error because it textually precedes the declaration of the variable. En el método G, el uso de j en el inicializador para la declaración de j es válido porque el uso no precede a local_variable_declarator.In the G method, the use of j in the initializer for the declaration of j is valid because the use does not precede the local_variable_declarator. En el método H, un local_variable_declarator subsiguiente hace referencia correctamente a una variable local declarada en un local_variable_declarator anterior dentro del mismo local_variable_declaration.In the H method, a subsequent local_variable_declarator correctly refers to a local variable declared in an earlier local_variable_declarator within the same local_variable_declaration.

Las reglas de ámbito de las variables locales están diseñadas para garantizar que el significado de un nombre usado en un contexto de expresión siempre es el mismo dentro de un bloque.The scoping rules for local variables are designed to guarantee that the meaning of a name used in an expression context is always the same within a block. Si el ámbito de una variable local solo se extiende desde su declaración hasta el final del bloque, en el ejemplo anterior, la primera asignación se asignaría a la variable de instancia y la segunda asignación asignaría a la variable local, lo que posiblemente provocaría errores en tiempo de compilación si las instrucciones del bloque se van a reorganizar posteriormente.If the scope of a local variable were to extend only from its declaration to the end of the block, then in the example above, the first assignment would assign to the instance variable and the second assignment would assign to the local variable, possibly leading to compile-time errors if the statements of the block were later to be rearranged.

El significado de un nombre dentro de un bloque puede variar en función del contexto en el que se usa el nombre.The meaning of a name within a block may differ based on the context in which the name is used. En el ejemploIn the example

using System;

class A {}

class Test
{
    static void Main() {
        string A = "hello, world";
        string s = A;                            // expression context

        Type t = typeof(A);                      // type context

        Console.WriteLine(s);                    // writes "hello, world"
        Console.WriteLine(t);                    // writes "A"
    }
}

el nombre A se usa en un contexto de expresión para hacer referencia a la variable local A y en un contexto de tipo para hacer referencia a la clase A.the name A is used in an expression context to refer to the local variable A and in a type context to refer to the class A.

Ocultación de nombresName hiding

El ámbito de una entidad suele abarcar más texto del programa que el espacio de declaración de la entidad.The scope of an entity typically encompasses more program text than the declaration space of the entity. En concreto, el ámbito de una entidad puede incluir declaraciones que introducen nuevos espacios de declaración que contienen entidades con el mismo nombre.In particular, the scope of an entity may include declarations that introduce new declaration spaces containing entities of the same name. Dichas declaraciones hacen que la entidad original se oculte.Such declarations cause the original entity to become hidden. Por el contrario, se dice que una entidad es visible cuando no está oculta.Conversely, an entity is said to be visible when it is not hidden.

La ocultación de nombres se produce cuando los ámbitos se superponen mediante anidamiento y cuando los ámbitos se superponen a través de la herencia.Name hiding occurs when scopes overlap through nesting and when scopes overlap through inheritance. En las secciones siguientes se describen las características de los dos tipos de ocultación.The characteristics of the two types of hiding are described in the following sections.

Ocultar mediante anidamientoHiding through nesting

La ocultación de nombres mediante el anidamiento puede producirse como resultado de anidar espacios de nombres o tipos dentro de los espacios de nombres, como resultado de anidar tipos dentro de clases o Structs, y como resultado de parámetros y declaraciones de variables locales.Name hiding through nesting can occur as a result of nesting namespaces or types within namespaces, as a result of nesting types within classes or structs, and as a result of parameter and local variable declarations.

En el ejemploIn the example

class A
{
    int i = 0;

    void F() {
        int i = 1;
    }

    void G() {
        i = 1;
    }
}

dentro del método F, la variable de instancia i está oculta por la variable local i, pero dentro del método G, i todavía hace referencia a la variable de instancia.within the F method, the instance variable i is hidden by the local variable i, but within the G method, i still refers to the instance variable.

Cuando un nombre de un ámbito interno oculta un nombre en un ámbito externo, oculta todas las apariciones sobrecargadas de ese nombre.When a name in an inner scope hides a name in an outer scope, it hides all overloaded occurrences of that name. En el ejemploIn the example

class Outer
{
    static void F(int i) {}

    static void F(string s) {}

    class Inner
    {
        void G() {
            F(1);              // Invokes Outer.Inner.F
            F("Hello");        // Error
        }

        static void F(long l) {}
    }
}

la llamada a F(1) invoca el F declarado en @no__t 2 porque todas las repeticiones externas de F están ocultas por la declaración interna.the call F(1) invokes the F declared in Inner because all outer occurrences of F are hidden by the inner declaration. Por la misma razón, la llamada a F("Hello") produce un error en tiempo de compilación.For the same reason, the call F("Hello") results in a compile-time error.

Ocultar a través de la herenciaHiding through inheritance

La ocultación de nombres a través de la herencia se produce cuando las clases o Structs declaran nombres que se heredaron de clases base.Name hiding through inheritance occurs when classes or structs redeclare names that were inherited from base classes. Este tipo de ocultación de nombres adopta uno de los siguientes formatos:This type of name hiding takes one of the following forms:

  • Una constante, un campo, una propiedad, un evento o un tipo introducidos en una clase o struct oculta todos los miembros de clase base con el mismo nombre.A constant, field, property, event, or type introduced in a class or struct hides all base class members with the same name.
  • Un método introducido en una clase o struct oculta todos los miembros de clase base que no son de método con el mismo nombre y todos los métodos de clase base con la misma firma (nombre de método y número de parámetros, modificadores y tipos).A method introduced in a class or struct hides all non-method base class members with the same name, and all base class methods with the same signature (method name and parameter count, modifiers, and types).
  • Un indizador introducido en una clase o struct oculta todos los indizadores de clase base con la misma firma (número de parámetros y tipos).An indexer introduced in a class or struct hides all base class indexers with the same signature (parameter count and types).

Las reglas que rigen las declaraciones de operador (operadores) hacen imposible que una clase derivada declare un operador con la misma signatura que un operador en una clase base.The rules governing operator declarations (Operators) make it impossible for a derived class to declare an operator with the same signature as an operator in a base class. Por lo tanto, los operadores nunca se ocultan entre sí.Thus, operators never hide one another.

Al contrario que ocultar un nombre de un ámbito externo, si se oculta un nombre accesible desde un ámbito heredado, se genera una advertencia.Contrary to hiding a name from an outer scope, hiding an accessible name from an inherited scope causes a warning to be reported. En el ejemploIn the example

class Base
{
    public void F() {}
}

class Derived: Base
{
    public void F() {}        // Warning, hiding an inherited name
}

la declaración de F en Derived provoca la notificación de una advertencia.the declaration of F in Derived causes a warning to be reported. Ocultar un nombre heredado no es específicamente un error, ya que esto impedirá la evolución independiente de las clases base.Hiding an inherited name is specifically not an error, since that would preclude separate evolution of base classes. Por ejemplo, la situación anterior podría haber surgido debido a que una versión posterior de Base presentó un método F que no estaba presente en una versión anterior de la clase.For example, the above situation might have come about because a later version of Base introduced an F method that wasn't present in an earlier version of the class. Si la situación anterior hubiera sido un error, cualquier cambio realizado en una clase base en una biblioteca de clases con versiones independientes podría provocar que las clases derivadas dejen de ser válidas.Had the above situation been an error, then any change made to a base class in a separately versioned class library could potentially cause derived classes to become invalid.

La advertencia causada por ocultar un nombre heredado se puede eliminar mediante el uso del modificador new:The warning caused by hiding an inherited name can be eliminated through use of the new modifier:

class Base
{
    public void F() {}
}

class Derived: Base
{
    new public void F() {}
}

El modificador new indica que el F de Derived es "New" y que, en realidad, está pensado para ocultar el miembro heredado.The new modifier indicates that the F in Derived is "new", and that it is indeed intended to hide the inherited member.

Una declaración de un nuevo miembro oculta un miembro heredado solo dentro del ámbito del nuevo miembro.A declaration of a new member hides an inherited member only within the scope of the new member.

class Base
{
    public static void F() {}
}

class Derived: Base
{
    new private static void F() {}    // Hides Base.F in Derived only
}

class MoreDerived: Derived
{
    static void G() { F(); }          // Invokes Base.F
}

En el ejemplo anterior, la declaración de F en Derived oculta el @no__t 2 que se heredó de Base, pero como el nuevo F en Derived tiene acceso privado, su ámbito no se extiende a MoreDerived.In the example above, the declaration of F in Derived hides the F that was inherited from Base, but since the new F in Derived has private access, its scope does not extend to MoreDerived. Por lo tanto, la llamada F() en MoreDerived.G es válida y llamará a @no__t 2.Thus, the call F() in MoreDerived.G is valid and will invoke Base.F.

Nombres de espacios de nombres y tiposNamespace and type names

Varios contextos de un C# programa requieren que se especifique un namespace_name o type_name .Several contexts in a C# program require a namespace_name or a type_name to be specified.

namespace_name
    : namespace_or_type_name
    ;

type_name
    : namespace_or_type_name
    ;

namespace_or_type_name
    : identifier type_argument_list?
    | namespace_or_type_name '.' identifier type_argument_list?
    | qualified_alias_member
    ;

Un namespace_name es un namespace_or_type_name que hace referencia a un espacio de nombres.A namespace_name is a namespace_or_type_name that refers to a namespace. Después de la resolución tal y como se describe a continuación, el namespace_or_type_name de un namespace_name debe hacer referencia a un espacio de nombres o, de lo contrario, se producirá un error en tiempo de compilación.Following resolution as described below, the namespace_or_type_name of a namespace_name must refer to a namespace, or otherwise a compile-time error occurs. Ningún argumento de tipo (argumentos de tipo) puede estar presente en un namespace_name (solo los tipos pueden tener argumentos de tipo).No type arguments (Type arguments) can be present in a namespace_name (only types can have type arguments).

Un type_name es un namespace_or_type_name que hace referencia a un tipo.A type_name is a namespace_or_type_name that refers to a type. Después de la resolución tal y como se describe a continuación, el namespace_or_type_name de un type_name debe hacer referencia a un tipo o, de lo contrario, se producirá un error en tiempo de compilación.Following resolution as described below, the namespace_or_type_name of a type_name must refer to a type, or otherwise a compile-time error occurs.

Si el namespace_or_type_name es un miembro de alias calificado, su significado es como se describe en calificadores de alias de espacio de nombres.If the namespace_or_type_name is a qualified-alias-member its meaning is as described in Namespace alias qualifiers. De lo contrario, un namespace_or_type_name tiene una de cuatro formas:Otherwise, a namespace_or_type_name has one of four forms:

  • I
  • I<A1, ..., Ak>
  • N.I
  • N.I<A1, ..., Ak>

donde I es un identificador único, N es un namespace_or_type_name y <A1, ..., Ak> es un type_argument_listopcional.where I is a single identifier, N is a namespace_or_type_name and <A1, ..., Ak> is an optional type_argument_list. Si no se especifica type_argument_list , considere la posibilidad de k para que sea cero.When no type_argument_list is specified, consider k to be zero.

El significado de un namespace_or_type_name se determina de la siguiente manera:The meaning of a namespace_or_type_name is determined as follows:

  • Si el namespace_or_type_name tiene el formato I o el formulario I<A1, ..., Ak>:If the namespace_or_type_name is of the form I or of the form I<A1, ..., Ak>:
    • Si K es cero y namespace_or_type_name aparece dentro de una declaración de método genérico (métodos) y la Declaración incluye un parámetro de tipo (parámetros de tipo) con el nombre @ no__t-4, entonces namespace_or_type_ nombre hace referencia a ese parámetro de tipo.If K is zero and the namespace_or_type_name appears within a generic method declaration (Methods) and if that declaration includes a type parameter (Type parameters) with name I, then the namespace_or_type_name refers to that type parameter.
    • De lo contrario, si el namespace_or_type_name aparece dentro de una declaración de tipos, por cada tipo de instancia @ no__t-1 (el tipo de instancia), empezando por el tipo de instancia de esa declaración de tipos y continuando con el tipo de instancia de cada uno Declaración de clase o estructura envolvente (si existe):Otherwise, if the namespace_or_type_name appears within a type declaration, then for each instance type T (The instance type), starting with the instance type of that type declaration and continuing with the instance type of each enclosing class or struct declaration (if any):
      • Si K es cero y la declaración de T incluye un parámetro de tipo con el nombre @ no__t-2, el namespace_or_type_name hace referencia a ese parámetro de tipo.If K is zero and the declaration of T includes a type parameter with name I, then the namespace_or_type_name refers to that type parameter.
      • De lo contrario, si el namespace_or_type_name aparece dentro del cuerpo de la declaración de tipos, y T o cualquiera de sus tipos base contienen un tipo accesible anidado con los parámetros Name @ no__t-2 y K @ no__t-4Type, namespace_or_type _name hace referencia a ese tipo construido con los argumentos de tipo especificados.Otherwise, if the namespace_or_type_name appears within the body of the type declaration, and T or any of its base types contain a nested accessible type having name I and K type parameters, then the namespace_or_type_name refers to that type constructed with the given type arguments. Si hay más de un tipo de este tipo, se selecciona el tipo declarado en el tipo más derivado.If there is more than one such type, the type declared within the more derived type is selected. Tenga en cuenta que los miembros que no son de tipo (constantes, campos, métodos, propiedades, indizadores, operadores, constructores de instancias, destructores y constructores estáticos) y miembros de tipo con un número diferente de parámetros de tipo se omiten al determinar el significado del namespace_or_type_name.Note that non-type members (constants, fields, methods, properties, indexers, operators, instance constructors, destructors, and static constructors) and type members with a different number of type parameters are ignored when determining the meaning of the namespace_or_type_name.
    • Si los pasos anteriores no se realizaron correctamente, para cada espacio de nombres @ no__t-0, empezando por el espacio de nombres en el que se produce namespace_or_type_name , continuando con cada espacio de nombres envolvente (si existe) y finalizando con el espacio de nombres global, lo siguiente los pasos se evalúan hasta que se encuentra una entidad:If the previous steps were unsuccessful then, for each namespace N, starting with the namespace in which the namespace_or_type_name occurs, continuing with each enclosing namespace (if any), and ending with the global namespace, the following steps are evaluated until an entity is located:
      • Si K es cero y I es el nombre de un espacio de nombres en @ no__t-2, entonces:If K is zero and I is the name of a namespace in N, then:
        • Si la ubicación donde se produce el namespace_or_type_name se incluye en una declaración de espacio de nombres para N y la declaración del espacio de nombres contiene un extern_alias_directive o un using_alias_directive que asocia el nombre @ no __t-4 con un espacio de nombres o un tipo, el namespace_or_type_name es ambiguo y se produce un error en tiempo de compilación.If the location where the namespace_or_type_name occurs is enclosed by a namespace declaration for N and the namespace declaration contains an extern_alias_directive or using_alias_directive that associates the name I with a namespace or type, then the namespace_or_type_name is ambiguous and a compile-time error occurs.
        • De lo contrario, namespace_or_type_name hace referencia al espacio de nombres denominado I en N.Otherwise, the namespace_or_type_name refers to the namespace named I in N.
      • De lo contrario, si N contiene un tipo accesible con los parámetros Name @ no__t-1 y K @ no__t-3type, entonces:Otherwise, if N contains an accessible type having name I and K type parameters, then:
        • Si K es cero y la ubicación donde se produce el namespace_or_type_name se incluye en una declaración de espacio de nombres para N y la declaración del espacio de nombres contiene un extern_alias_directive o using_alias_directive que asocia el nombre @ no__t-5 con un espacio de nombres o tipo, el namespace_or_type_name es ambiguo y se produce un error en tiempo de compilación.If K is zero and the location where the namespace_or_type_name occurs is enclosed by a namespace declaration for N and the namespace declaration contains an extern_alias_directive or using_alias_directive that associates the name I with a namespace or type, then the namespace_or_type_name is ambiguous and a compile-time error occurs.
        • De lo contrario, namespace_or_type_name hace referencia al tipo construido con los argumentos de tipo especificados.Otherwise, the namespace_or_type_name refers to the type constructed with the given type arguments.
      • De lo contrario, si la ubicación donde se produce el namespace_or_type_name se incluye en una declaración de espacio de nombres para N:Otherwise, if the location where the namespace_or_type_name occurs is enclosed by a namespace declaration for N:
        • Si K es cero y la declaración del espacio de nombres contiene un extern_alias_directive o un using_alias_directive que asocia el nombre @ no__t-3 con un espacio de nombres o tipo importado, el namespace_or_type_name hace referencia a ese espacio de nombres o tipo.If K is zero and the namespace declaration contains an extern_alias_directive or using_alias_directive that associates the name I with an imported namespace or type, then the namespace_or_type_name refers to that namespace or type.
        • De lo contrario, si los espacios de nombres y las declaraciones de tipos importados por using_namespace_directives y using_alias_directives de la declaración del espacio de nombres contienen exactamente un tipo accesible con el nombre @ no__t-2 y K @ no__t-4Type los parámetros, después, el namespace_or_type_name hace referencia a ese tipo construido con los argumentos de tipo especificados.Otherwise, if the namespaces and type declarations imported by the using_namespace_directives and using_alias_directives of the namespace declaration contain exactly one accessible type having name I and K type parameters, then the namespace_or_type_name refers to that type constructed with the given type arguments.
        • De lo contrario, si los espacios de nombres y las declaraciones de tipos importados por using_namespace_directives y using_alias_directives de la declaración del espacio de nombres contienen más de un tipo accesible con el nombre @ no__t-2 y K @ no__t-4Type los parámetros, namespace_or_type_name , son ambiguos y se produce un error.Otherwise, if the namespaces and type declarations imported by the using_namespace_directives and using_alias_directives of the namespace declaration contain more than one accessible type having name I and K type parameters, then the namespace_or_type_name is ambiguous and an error occurs.
    • De lo contrario, namespace_or_type_name no está definido y se produce un error en tiempo de compilación.Otherwise, the namespace_or_type_name is undefined and a compile-time error occurs.
  • De lo contrario, el namespace_or_type_name tiene el formato N.I o el formato N.I<A1, ..., Ak>.Otherwise, the namespace_or_type_name is of the form N.I or of the form N.I<A1, ..., Ak>. N se resuelve primero como namespace_or_type_name.N is first resolved as a namespace_or_type_name. Si la resolución de N no se realiza correctamente, se produce un error en tiempo de compilación.If the resolution of N is not successful, a compile-time error occurs. De lo contrario, N.I o N.I<A1, ..., Ak> se resuelve como sigue:Otherwise, N.I or N.I<A1, ..., Ak> is resolved as follows:
    • Si K es cero y N hace referencia a un espacio de nombres y N contiene un espacio de nombres anidado con el nombre I, el namespace_or_type_name hace referencia a ese espacio de nombres anidado.If K is zero and N refers to a namespace and N contains a nested namespace with name I, then the namespace_or_type_name refers to that nested namespace.
    • De lo contrario, si N hace referencia a un espacio de nombres y N contiene un tipo accesible con los parámetros Name @ no__t-2 y K @ no__t-4Type, el namespace_or_type_name hace referencia a ese tipo construido con los argumentos de tipo especificados.Otherwise, if N refers to a namespace and N contains an accessible type having name I and K type parameters, then the namespace_or_type_name refers to that type constructed with the given type arguments.
    • De lo contrario, si N hace referencia a un tipo de clase o struct (posiblemente construido) y N o cualquiera de sus clases base contienen un tipo accesible anidado con los parámetros Name @ no__t-2 y K @ no__t-4Type, el namespace_or_type_name hace referencia a ese tipo construido con los argumentos de tipo especificados.Otherwise, if N refers to a (possibly constructed) class or struct type and N or any of its base classes contain a nested accessible type having name I and K type parameters, then the namespace_or_type_name refers to that type constructed with the given type arguments. Si hay más de un tipo de este tipo, se selecciona el tipo declarado en el tipo más derivado.If there is more than one such type, the type declared within the more derived type is selected. Tenga en cuenta que si el significado de N.I se está determinando como parte de la resolución de la especificación de clase base de N, la clase base directa de N se considera objeto (clases base).Note that if the meaning of N.I is being determined as part of resolving the base class specification of N then the direct base class of N is considered to be object (Base classes).
    • De lo contrario, N.I es un namespace_or_type_nameno válido y se produce un error en tiempo de compilación.Otherwise, N.I is an invalid namespace_or_type_name, and a compile-time error occurs.

Una namespace_or_type_name puede hacer referencia a una clase estática (clases estáticas) solo siA namespace_or_type_name is permitted to reference a static class (Static classes) only if

  • Namespace_or_type_name es el T en un namespace_or_type_name con el formato T.I, o bienThe namespace_or_type_name is the T in a namespace_or_type_name of the form T.I, or
  • Namespace_or_type_name es el T en typeof_expression (listas deargumentos1) con el formato typeof(T).The namespace_or_type_name is the T in a typeof_expression (Argument lists1) of the form typeof(T).

Nombres completosFully qualified names

Cada espacio de nombres y tipo tiene un nombre completo, que identifica de forma única el espacio de nombres o el tipo entre todos los demás.Every namespace and type has a fully qualified name, which uniquely identifies the namespace or type amongst all others. El nombre completo de un espacio de nombres o tipo N se determina de la siguiente manera:The fully qualified name of a namespace or type N is determined as follows:

  • Si N es un miembro del espacio de nombres global, su nombre completo es N.If N is a member of the global namespace, its fully qualified name is N.
  • De lo contrario, su nombre completo es S.N, donde S es el nombre completo del espacio de nombres o tipo en el que se declara N.Otherwise, its fully qualified name is S.N, where S is the fully qualified name of the namespace or type in which N is declared.

En otras palabras, el nombre completo de N es la ruta de acceso jerárquica completa de los identificadores que conducen a N, comenzando por el espacio de nombres global.In other words, the fully qualified name of N is the complete hierarchical path of identifiers that lead to N, starting from the global namespace. Dado que cada miembro de un espacio de nombres o tipo debe tener un nombre único, sigue que el nombre completo de un espacio de nombres o tipo es siempre único.Because every member of a namespace or type must have a unique name, it follows that the fully qualified name of a namespace or type is always unique.

En el ejemplo siguiente se muestran varias declaraciones de espacio de nombres y tipo junto con sus nombres completos asociados.The example below shows several namespace and type declarations along with their associated fully qualified names.

class A {}                // A

namespace X               // X
{
    class B               // X.B
    {
        class C {}        // X.B.C
    }

    namespace Y           // X.Y
    {
        class D {}        // X.Y.D
    }
}

namespace X.Y             // X.Y
{
    class E {}            // X.Y.E
}

Administración de memoria automáticaAutomatic memory management

C#emplea la administración de memoria automática, que libera a los desarrolladores de la asignación y liberación manuales de la memoria ocupada por los objetos.C# employs automatic memory management, which frees developers from manually allocating and freeing the memory occupied by objects. Las directivas de administración de memoria automática se implementan mediante un recolector de elementos no utilizados.Automatic memory management policies are implemented by a garbage collector. El ciclo de vida de la administración de memoria de un objeto es el siguiente:The memory management life cycle of an object is as follows:

  1. Cuando se crea el objeto, se le asigna memoria, se ejecuta el constructor y el objeto se considera activo.When the object is created, memory is allocated for it, the constructor is run, and the object is considered live.
  2. Si no se puede tener acceso al objeto, o a cualquier parte del mismo, por cualquier continuación posible de ejecución, que no sea la ejecución de destructores, el objeto se considera que ya no está en uso y se puede elegir para su destrucción.If the object, or any part of it, cannot be accessed by any possible continuation of execution, other than the running of destructors, the object is considered no longer in use, and it becomes eligible for destruction. El C# compilador y el recolector de elementos no utilizados pueden optar por analizar el código para determinar qué referencias a un objeto se pueden usar en el futuro.The C# compiler and the garbage collector may choose to analyze code to determine which references to an object may be used in the future. Por ejemplo, si una variable local que se encuentra en el ámbito es la única referencia existente a un objeto, pero nunca se hace referencia a esa variable local en ninguna continuación posible de ejecución del punto de ejecución actual del procedimiento, el recolector de elementos no utilizados puede (pero no es obligatorio para) tratar el objeto como ya no está en uso.For instance, if a local variable that is in scope is the only existing reference to an object, but that local variable is never referred to in any possible continuation of execution from the current execution point in the procedure, the garbage collector may (but is not required to) treat the object as no longer in use.
  3. Una vez que el objeto es válido para la destrucción, en algún momento posterior no especificado, se ejecuta el destructor(destructores) (si existe) para el objeto.Once the object is eligible for destruction, at some unspecified later time the destructor (Destructors) (if any) for the object is run. En circunstancias normales, el destructor del objeto solo se ejecuta una vez, aunque las API específicas de la implementación pueden permitir que se invalide este comportamiento.Under normal circumstances the destructor for the object is run once only, though implementation-specific APIs may allow this behavior to be overridden.
  4. Una vez que se ejecuta el destructor de un objeto, si no se puede tener acceso a ese objeto o a cualquier parte del mismo, cualquier continuación posible de ejecución, incluida la ejecución de destructores, el objeto se considera inaccesible y el objeto pasa a ser válido para la colección.Once the destructor for an object is run, if that object, or any part of it, cannot be accessed by any possible continuation of execution, including the running of destructors, the object is considered inaccessible and the object becomes eligible for collection.
  5. Por último, en algún momento después de que el objeto sea válido para la recolección, el recolector de elementos no utilizados libera la memoria asociada a ese objeto.Finally, at some time after the object becomes eligible for collection, the garbage collector frees the memory associated with that object.

El recolector de elementos no utilizados mantiene información sobre el uso de los objetos y usa esta información para tomar decisiones de administración de memoria, como la ubicación de la memoria para buscar un objeto recién creado, Cuándo se debe reubicar un objeto y cuándo un objeto ya no está en uso o es inaccesible.The garbage collector maintains information about object usage, and uses this information to make memory management decisions, such as where in memory to locate a newly created object, when to relocate an object, and when an object is no longer in use or inaccessible.

Al igual que otros lenguajes que suponen la existencia C# de un recolector de elementos no utilizados, está diseñado de modo que el recolector de elementos no utilizados pueda implementar una amplia gama de directivas de administración de memoria.Like other languages that assume the existence of a garbage collector, C# is designed so that the garbage collector may implement a wide range of memory management policies. Por ejemplo, C# no requiere que se ejecuten destructores o que los objetos se recopilen tan pronto como sean válidos, o que los destructores se ejecuten en un orden determinado o en un subproceso determinado.For instance, C# does not require that destructors be run or that objects be collected as soon as they are eligible, or that destructors be run in any particular order, or on any particular thread.

El comportamiento del recolector de elementos no utilizados puede controlarse, hasta cierto punto, a través de métodos estáticos en la clase System.GC.The behavior of the garbage collector can be controlled, to some degree, via static methods on the class System.GC. Esta clase se puede usar para solicitar que se produzca una colección, destructores que se van a ejecutar (o no ejecutar), etc.This class can be used to request a collection to occur, destructors to be run (or not run), and so forth.

Dado que el recolector de elementos no utilizados tiene una latitud ancha a la hora de decidir cuándo recopilar objetos y ejecutar destructores, una implementación compatible puede generar resultados que sean diferentes de los que se muestran en el código siguiente.Since the garbage collector is allowed wide latitude in deciding when to collect objects and run destructors, a conforming implementation may produce output that differs from that shown by the following code. El programaThe program

using System;

class A
{
    ~A() {
        Console.WriteLine("Destruct instance of A");
    }
}

class B
{
    object Ref;

    public B(object o) {
        Ref = o;
    }

    ~B() {
        Console.WriteLine("Destruct instance of B");
    }
}

class Test
{
    static void Main() {
        B b = new B(new A());
        b = null;
        GC.Collect();
        GC.WaitForPendingFinalizers();
    }
}

crea una instancia de la clase A y una instancia de la clase B.creates an instance of class A and an instance of class B. Estos objetos son válidos para la recolección de elementos no utilizados cuando la variable b tiene asignado el valor null, ya que, después de este tiempo, no es posible que ningún código escrito por el usuario tenga acceso a ellos.These objects become eligible for garbage collection when the variable b is assigned the value null, since after this time it is impossible for any user-written code to access them. El resultado puede serThe output could be either

Destruct instance of A
Destruct instance of B

oor

Destruct instance of B
Destruct instance of A

Dado que el lenguaje no impone ninguna restricción en el orden en el que los objetos se recolectan como elementos no utilizados.because the language imposes no constraints on the order in which objects are garbage collected.

En casos sutiles, la distinción entre "candidato a la destrucción" y "puede ser válida para la recopilación" puede ser importante.In subtle cases, the distinction between "eligible for destruction" and "eligible for collection" can be important. Por ejemplo,For example,

using System;

class A
{
    ~A() {
        Console.WriteLine("Destruct instance of A");
    }

    public void F() {
        Console.WriteLine("A.F");
        Test.RefA = this;
    }
}

class B
{
    public A Ref;

    ~B() {
        Console.WriteLine("Destruct instance of B");
        Ref.F();
    }
}

class Test
{
    public static A RefA;
    public static B RefB;

    static void Main() {
        RefB = new B();
        RefA = new A();
        RefB.Ref = RefA;
        RefB = null;
        RefA = null;

        // A and B now eligible for destruction
        GC.Collect();
        GC.WaitForPendingFinalizers();

        // B now eligible for collection, but A is not
        if (RefA != null)
            Console.WriteLine("RefA is not null");
    }
}

En el programa anterior, si el recolector de elementos no utilizados elige ejecutar el destructor de A antes del destructor de B, la salida de este programa podría ser:In the above program, if the garbage collector chooses to run the destructor of A before the destructor of B, then the output of this program might be:

Destruct instance of A
Destruct instance of B
A.F
RefA is not null

Tenga en cuenta que aunque la instancia de A no se estaba usando y se ejecutó el destructor de A, todavía es posible llamar a los métodos de A (en este caso, F) desde otro destructor.Note that although the instance of A was not in use and A's destructor was run, it is still possible for methods of A (in this case, F) to be called from another destructor. Además, tenga en cuenta que la ejecución de un destructor puede hacer que un objeto se pueda utilizar de nuevo desde el programa principal.Also, note that running of a destructor may cause an object to become usable from the mainline program again. En este caso, la ejecución del destructor B produjo una instancia de A que antes no estaba en uso para ser accesible desde la referencia activa Test.RefA.In this case, the running of B's destructor caused an instance of A that was previously not in use to become accessible from the live reference Test.RefA. Después de la llamada a WaitForPendingFinalizers, la instancia de B es válida para la recolección, pero la instancia de A no es, debido a la referencia Test.RefA.After the call to WaitForPendingFinalizers, the instance of B is eligible for collection, but the instance of A is not, because of the reference Test.RefA.

Para evitar la confusión y el comportamiento inesperado, suele ser una buena idea que los destructores solo realicen la limpieza en los datos almacenados en sus propios campos del objeto y no realicen ninguna acción en los objetos a los que se hace referencia ni en los campos estáticos.To avoid confusion and unexpected behavior, it is generally a good idea for destructors to only perform cleanup on data stored in their object's own fields, and not to perform any actions on referenced objects or static fields.

Una alternativa al uso de destructores es dejar que una clase implemente la interfaz System.IDisposable.An alternative to using destructors is to let a class implement the System.IDisposable interface. Esto permite al cliente del objeto determinar cuándo liberar los recursos del objeto, normalmente mediante el acceso al objeto como un recurso en una instrucción using (la instrucción using).This allows the client of the object to determine when to release the resources of the object, typically by accessing the object as a resource in a using statement (The using statement).

Orden de ejecuciónExecution order

La ejecución de C# un programa continúa de tal forma que los efectos secundarios de cada subproceso en ejecución se conserven en puntos de ejecución críticos.Execution of a C# program proceeds such that the side effects of each executing thread are preserved at critical execution points. Un efecto secundario se define como una lectura o escritura de un campo volátil, una escritura en una variable no volátil, una escritura en un recurso externo y el inicio de una excepción.A side effect is defined as a read or write of a volatile field, a write to a non-volatile variable, a write to an external resource, and the throwing of an exception. Los puntos de ejecución críticos en los que se debe conservar el orden de estos efectos secundarios son referencias a campos volátiles (campos volátiles), instrucciones lock (instrucción lock) y creación y terminación de subprocesos.The critical execution points at which the order of these side effects must be preserved are references to volatile fields (Volatile fields), lock statements (The lock statement), and thread creation and termination. El entorno de ejecución es gratuito para cambiar el orden de ejecución de C# un programa, sujeto a las siguientes restricciones:The execution environment is free to change the order of execution of a C# program, subject to the following constraints:

  • La dependencia de los datos se conserva dentro de un subproceso de ejecución.Data dependence is preserved within a thread of execution. Es decir, el valor de cada variable se calcula como si todas las instrucciones del subproceso se ejecutaran en el orden del programa original.That is, the value of each variable is computed as if all statements in the thread were executed in original program order.
  • Se conservan las reglas de ordenación de inicialización (inicialización de campos e inicializadores de variables).Initialization ordering rules are preserved (Field initialization and Variable initializers).
  • El orden de los efectos secundarios se conserva con respecto a las lecturas y escrituras volátiles (campos volátiles).The ordering of side effects is preserved with respect to volatile reads and writes (Volatile fields). Además, el entorno de ejecución no necesita evaluar parte de una expresión si puede deducir que el valor de esa expresión no se usa y que no se producen efectos secundarios necesarios (incluidos los causados por una llamada a un método o el acceso a un campo volátil).Additionally, the execution environment need not evaluate part of an expression if it can deduce that that expression's value is not used and that no needed side effects are produced (including any caused by calling a method or accessing a volatile field). Cuando se interrumpe la ejecución del programa mediante un evento asincrónico (como una excepción iniciada por otro subproceso), no se garantiza que los efectos secundarios observables estén visibles en el orden del programa original.When program execution is interrupted by an asynchronous event (such as an exception thrown by another thread), it is not guaranteed that the observable side effects are visible in the original program order.