Conceitos básicosBasic concepts

Inicialização de aplicativosApplication Startup

Um assembly que tem um Entry Point _ é chamado de _aplicativo*.An assembly that has an entry point _ is called an _application*. Quando um aplicativo é executado, um novo domínio _ aplicativo* é criado.When an application is run, a new _ application domain* is created. Várias instanciações diferentes de um aplicativo podem existir no mesmo computador ao mesmo tempo, e cada uma tem seu próprio domínio de aplicativo.Several different instantiations of an application may exist on the same machine at the same time, and each has its own application domain.

Um domínio de aplicativo habilita o isolamento de aplicativos agindo como um contêiner para o estado do aplicativo.An application domain enables application isolation by acting as a container for application state. Um domínio de aplicativo atua como um contêiner e limite para os tipos definidos no aplicativo e as bibliotecas de classes que ele usa.An application domain acts as a container and boundary for the types defined in the application and the class libraries it uses. Os tipos carregados em um domínio de aplicativo são diferentes do mesmo tipo carregado em outro domínio de aplicativo, e as instâncias de objetos não são diretamente compartilhadas entre domínios de aplicativo.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 exemplo, cada domínio de aplicativo tem sua própria cópia de variáveis estáticas para esses tipos, e um construtor estático para um tipo é executado no máximo uma vez por domínio de aplicativo.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. As implementações são gratuitas para fornecer políticas ou mecanismos específicos de implementação para a criação e destruição de domínios de aplicativo.Implementations are free to provide implementation-specific policy or mechanisms for the creation and destruction of application domains.

A inicialização do aplicativo ocorre quando o ambiente de execução chama um método designado, que é chamado de ponto de entrada do aplicativo.Application startup occurs when the execution environment calls a designated method, which is referred to as the application's entry point. Esse método de ponto de entrada sempre é nomeado Main e pode ter uma das seguintes assinaturas: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 mostrado, o ponto de entrada pode, opcionalmente, retornar um int valor.As shown, the entry point may optionally return an int value. Esse valor de retorno é usado na terminação do aplicativo (terminação do aplicativo).This return value is used in application termination (Application termination).

O ponto de entrada pode, opcionalmente, ter um parâmetro formal.The entry point may optionally have one formal parameter. O parâmetro pode ter qualquer nome, mas o tipo do parâmetro deve ser string[] .The parameter may have any name, but the type of the parameter must be string[]. Se o parâmetro formal estiver presente, o ambiente de execução criará e passará um string[] argumento contendo os argumentos de linha de comando que foram especificados quando o aplicativo foi iniciado.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. O string[] argumento nunca é nulo, mas pode ter um comprimento zero se nenhum argumento de linha de comando foi especificado.The string[] argument is never null, but it may have a length of zero if no command-line arguments were specified.

Como o C# dá suporte à sobrecarga de método, uma classe ou struct pode conter várias definições de algum método, desde que cada uma tenha uma assinatura diferente.Since C# supports method overloading, a class or struct may contain multiple definitions of some method, provided each has a different signature. No entanto, em um único programa, nenhuma classe ou estrutura pode conter mais de um método chamado Main cuja definição o qualifica para ser usado como um ponto de entrada de aplicativo.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. Outras versões sobrecarregadas do Main são permitidas, no entanto, desde que tenham mais de um parâmetro, ou seu único parâmetro seja diferente do 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[].

Um aplicativo pode ser composto por várias classes ou structs.An application can be made up of multiple classes or structs. É possível que mais de uma dessas classes ou structs contenham um método chamado Main cuja definição a qualifica para ser usada como um ponto de entrada de aplicativo.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. Nesses casos, um mecanismo externo (como uma opção de compilador de linha de comando) deve ser usado para selecionar um desses Main métodos como o ponto 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.

No C#, cada método deve ser definido como um membro de uma classe ou estrutura.In C#, every method must be defined as a member of a class or struct. Normalmente, a acessibilidade declarada (acessibilidade declarada) de um método é determinada pelos modificadores de acesso (modificadores de acesso) especificados em sua declaração e, da mesma forma, a acessibilidade declarada de um tipo é determinada pelos modificadores de acesso especificados em sua declaração.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 um determinado método de um determinado tipo seja chamado, o tipo e o membro devem estar acessíveis.In order for a given method of a given type to be callable, both the type and the member must be accessible. No entanto, o ponto de entrada do aplicativo é um caso especial.However, the application entry point is a special case. Especificamente, o ambiente de execução pode acessar o ponto de entrada do aplicativo independentemente de sua acessibilidade declarada e independentemente da acessibilidade declarada de suas declarações de tipo delimitador.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.

O método de ponto de entrada de aplicativo pode não estar em uma declaração de classe genérica.The application entry point method may not be in a generic class declaration.

Em todos os outros aspectos, os métodos de ponto de entrada se comportam como aqueles que não são pontos de entrada.In all other respects, entry point methods behave like those that are not entry points.

Terminação de aplicativosApplication termination

A terminação de aplicativo retorna o controle para o ambiente de execução.Application termination returns control to the execution environment.

Se o tipo de retorno do método do ponto de entrada* do aplicativo for int , o valor retornado funcionará como o código de status de encerramento _ * do aplicativo * *.If the return type of the application's entry point _ method is int, the value returned serves as the application's _termination status code**. A finalidade desse código é permitir a comunicação de êxito ou falha no ambiente de execução.The purpose of this code is to allow communication of success or failure to the execution environment.

Se o tipo de retorno do método de ponto de entrada for void , atingir a chave direita ( } ) que encerra esse método, ou executar uma return instrução que não tenha nenhuma expressão, resultará em um código de status de encerramento 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 do encerramento de um aplicativo, os destruidores para todos os seus objetos que ainda não foram coletados pelo lixo são chamados, a menos que essa limpeza tenha sido suprimida (por uma chamada para o método de biblioteca GC.SuppressFinalize , por exemplo).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).

DeclaraçõesDeclarations

As declarações em um programa C# definem os elementos constituintes do programa.Declarations in a C# program define the constituent elements of the program. Os programas em C# são organizados usando Namespaces (namespaces), que podem conter declarações de tipo e declarações de namespace aninhadas.C# programs are organized using namespaces (Namespaces), which can contain type declarations and nested namespace declarations. Declarações de tipo (declarações de tipo) são usadas para definir classes (classes), estruturas(structs), interfaces (interfaces), enumerações (enums) e delegados (delegados).Type declarations (Type declarations) are used to define classes (Classes), structs (Structs), interfaces (Interfaces), enums (Enums), and delegates (Delegates). Os tipos de membros permitidos em uma declaração de tipo dependem da forma da declaração de tipo.The kinds of members permitted in a type declaration depend on the form of the type declaration. Por exemplo, declarações de classe podem conter declarações para constantes (constantes), campos(campos), métodos (métodos), Propriedades (Propriedades), eventos (eventos), indexadores (indexadores), operadores (operadores), construtores de instância (construtores deinstância), construtores estáticos (construtores estáticos), destruidores (destruidores) e tipos aninhados (tipos aninhados).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).

Uma declaração define um nome no espaço de declaração ao qual a declaração pertence.A declaration defines a name in the declaration space to which the declaration belongs. Exceto para Membros sobrecarregados (assinaturas e sobrecarga), é um erro de tempo de compilação ter duas ou mais declarações que apresentam Membros com o mesmo nome em um espaço de declaração.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 é possível que um espaço de declaração contenha diferentes tipos de membros com o mesmo nome.It is never possible for a declaration space to contain different kinds of members with the same name. Por exemplo, um espaço de declaração nunca pode conter um campo e um método com o mesmo nome.For example, a declaration space can never contain a field and a method by the same name.

Há vários tipos diferentes de espaços de declaração, conforme descrito a seguir.There are several different types of declaration spaces, as described in the following.

  • Em todos os arquivos de origem de um programa, namespace_member_declaration s sem namespace_declaration delimitadores são membros de um único espaço de declaração combinado chamado de espaço de declaração global.Within all source files of a program, namespace_member_declaration s with no enclosing namespace_declaration are members of a single combined declaration space called the global declaration space.
  • Em todos os arquivos de origem de um programa, namespace_member_declaration s em namespace_declaration s que têm o mesmo nome de namespace totalmente qualificado são membros de um único espaço de declaração combinado.Within all source files of a program, namespace_member_declaration s within namespace_declaration s that have the same fully qualified namespace name are members of a single combined declaration space.
  • Cada declaração de classe, struct ou interface cria um novo espaço de declaração.Each class, struct, or interface declaration creates a new declaration space. Os nomes são introduzidos nesse espaço de declaração por meio de class_member_declaration s, struct_member_declaration s, interface_member_declaration s ou type_parameter s.Names are introduced into this declaration space through class_member_declaration s, struct_member_declaration s, interface_member_declaration s, or type_parameter s. Exceto para declarações de construtor de instância sobrecarregadas e declarações de Construtor estáticos, uma classe ou struct não pode conter uma declaração de membro com o mesmo nome que a classe ou struct.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. Uma classe, estrutura ou interface permite a declaração de métodos e indexadores sobrecarregados.A class, struct, or interface permits the declaration of overloaded methods and indexers. Além disso, uma classe ou struct permite a declaração de operadores e construtores de instância sobrecarregados.Furthermore, a class or struct permits the declaration of overloaded instance constructors and operators. Por exemplo, uma classe, struct ou interface pode conter várias declarações de método com o mesmo nome, desde que essas declarações de método difiram em sua assinatura (assinaturas e 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). Observe que as classes base não contribuem para o espaço de declaração de uma classe, e as interfaces base não contribuem para o espaço de declaração de uma interface.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. Assim, uma classe ou interface derivada tem permissão para declarar um membro com o mesmo nome de um membro herdado.Thus, a derived class or interface is allowed to declare a member with the same name as an inherited member. Esse membro é dito para ocultar o membro herdado.Such a member is said to hide the inherited member.
  • Cada declaração de delegado cria um novo espaço de declaração.Each delegate declaration creates a new declaration space. Os nomes são introduzidos nesse espaço de declaração por meio de parâmetros formais (fixed_parameter s e parameter_array s) e type_parameter s.Names are introduced into this declaration space through formal parameters (fixed_parameter s and parameter_array s) and type_parameter s.
  • Cada declaração de enumeração cria um novo espaço de declaração.Each enumeration declaration creates a new declaration space. Os nomes são introduzidos nesse espaço de declaração por meio de enum_member_declarations.Names are introduced into this declaration space through enum_member_declarations.
  • Cada declaração de método, declaração de indexador, declaração de operador, declaração de construtor de instância e função anônima cria um novo espaço de declaração chamado *espaço de declaração de variável 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 _. Os nomes são introduzidos nesse espaço de declaração por meio de parâmetros formais (_fixed_parameter * s e parameter_array s) e type_parameter s.Names are introduced into this declaration space through formal parameters (_fixed_parameter*s and parameter_array s) and type_parameter s. O corpo do membro da função ou da função anônima, se houver, será considerado aninhado dentro do espaço de declaração da variável local.The body of the function member or anonymous function, if any, is considered to be nested within the local variable declaration space. É um erro para um espaço de declaração de variável local e um espaço de declaração de variável local aninhada para conter elementos com o mesmo nome.It is an error for a local variable declaration space and a nested local variable declaration space to contain elements with the same name. Portanto, dentro de um espaço de declaração aninhada não é possível declarar uma variável local ou constante com o mesmo nome de uma variável local ou constante em um espaço de declaração de delimitador.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. É possível que dois espaços de declaração contenham elementos com o mesmo nome, desde que nenhum espaço de declaração contenha o outro.It is possible for two declaration spaces to contain elements with the same name as long as neither declaration space contains the other.
  • Cada bloco ou switch_block , bem como uma instrução for, foreach e using , cria um espaço de declaração de variável local para variáveis locais e constantes locais.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 . Os nomes são introduzidos nesse espaço de declaração por meio de local_variable_declaration s e local_constant_declaration s.Names are introduced into this declaration space through local_variable_declaration s and local_constant_declaration s. Observe que os blocos que ocorrem como ou dentro do corpo de um membro de função ou função anônima são aninhados dentro do espaço de declaração de variável local declarado por essas funções para seus 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. Portanto, é um erro ter, por exemplo, um método com uma variável local e um parâmetro de mesmo nome.Thus it is an error to have e.g. a method with a local variable and a parameter of the same name.
  • Cada bloco ou switch_block cria um espaço de declaração separado para rótulos.Each block or switch_block creates a separate declaration space for labels. Os nomes são introduzidos nesse espaço de declaração por meio de labeled_statement s e os nomes são referenciados por meio de goto_statement s.Names are introduced into this declaration space through labeled_statement s, and the names are referenced through goto_statement s. O espaço de declaração de rótulo de um bloco inclui todos os blocos aninhados.The label declaration space of a block includes any nested blocks. Portanto, em um bloco aninhado não é possível declarar um rótulo com o mesmo nome de um rótulo em um bloco delimitador.Thus, within a nested block it is not possible to declare a label with the same name as a label in an enclosing block.

Em geral, a ordem textual na qual os nomes são declarados não é significado.The textual order in which names are declared is generally of no significance. Em particular, a ordem textual não é significativa para a declaração e o uso de namespaces, constantes, métodos, propriedades, eventos, indexadores, operadores, construtores de instância, destruidores, construtores estáticos e 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. A ordem de declaração é significativa das seguintes maneiras:Declaration order is significant in the following ways:

  • A ordem de declaração para declarações de campo e declarações de variáveis locais determina a ordem na qual seus inicializadores (se houver) são executados.Declaration order for field declarations and local variable declarations determines the order in which their initializers (if any) are executed.
  • As variáveis locais devem ser definidas antes de serem usadas (escopos).Local variables must be defined before they are used (Scopes).
  • A ordem de declaração para declarações de membro de enumeração (membros de enum) é significativa quando valores de constant_expression são omitidos.Declaration order for enum member declarations (Enum members) is significant when constant_expression values are omitted.

O espaço de declaração de um namespace é "Open finalizado" e duas declarações de namespace com o mesmo nome totalmente qualificado contribuem para o mesmo espaço de declaração.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 exemplo,For example

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

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

As duas declarações de namespace acima contribuem para o mesmo espaço de declaração, neste caso, declarando duas classes com os nomes totalmente qualificados Megacorp.Data.Customer e 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. Como as duas declarações contribuem para o mesmo espaço de declaração, ela causaria um erro de tempo de compilação se cada uma continha uma declaração de uma classe com o mesmo nome.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.

Conforme especificado acima, o espaço de declaração de um bloco inclui todos os blocos aninhados.As specified above, the declaration space of a block includes any nested blocks. Portanto, no exemplo a seguir, os F G métodos e resultam em um erro de tempo de compilação porque o nome i é declarado no bloco externo e não pode ser declarado novamente no bloco 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. No entanto, os H I métodos e são válidos, já que os dois i são declarados em blocos não aninhados separados.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();
    }
}

MembrosMembers

Namespaces e tipos têm Membros.Namespaces and types have members. Os membros de uma entidade estão geralmente disponíveis por meio do uso de um nome qualificado que começa com uma referência à entidade, seguida por um . token "", seguido pelo nome do membro.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.

Os membros de um tipo são declarados na declaração de tipo ou herdados da classe base do tipo.Members of a type are either declared in the type declaration or inherited from the base class of the type. Quando um tipo é herdado de uma classe base, todos os membros da classe base, exceto construtores de instância, destruidores e construtores estáticos, se tornam membros do 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. A acessibilidade declarada de um membro de classe base não controla se o membro é herdado — a herança se estende a qualquer membro que não seja um construtor de instância, construtor estático ou destruidor.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. No entanto, um membro herdado pode não estar acessível em um tipo derivado, devido à sua acessibilidade declarada (acessibilidade declarada) ou porque está ocultada por uma declaração no próprio tipo (ocultando por herança).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).

Membros de namespaceNamespace members

Namespaces e tipos que não têm namespace delimitador são membros do namespace global.Namespaces and types that have no enclosing namespace are members of the global namespace. Isso corresponde diretamente aos nomes declarados no espaço de declaração global.This corresponds directly to the names declared in the global declaration space.

Namespaces e tipos declarados em um namespace são membros desse namespace.Namespaces and types declared within a namespace are members of that namespace. Isso corresponde diretamente aos nomes declarados no espaço de declaração do namespace.This corresponds directly to the names declared in the declaration space of the namespace.

Namespaces não têm nenhuma restrição de acesso.Namespaces have no access restrictions. Não é possível declarar namespaces privados, protegidos ou internos, e os nomes de namespace são sempre acessíveis publicamente.It is not possible to declare private, protected, or internal namespaces, and namespace names are always publicly accessible.

Membros de structStruct members

Os membros de uma struct são os membros declarados na struct e os membros herdados da classe base direta da struct System.ValueType e a classe base indireta 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.

Os membros de um tipo simples correspondem diretamente aos membros do tipo struct com o alias do tipo simples:The members of a simple type correspond directly to the members of the struct type aliased by the simple type:

  • Os membros de sbyte são os membros da System.SByte estrutura.The members of sbyte are the members of the System.SByte struct.
  • Os membros de byte são os membros da System.Byte estrutura.The members of byte are the members of the System.Byte struct.
  • Os membros de short são os membros da System.Int16 estrutura.The members of short are the members of the System.Int16 struct.
  • Os membros de ushort são os membros da System.UInt16 estrutura.The members of ushort are the members of the System.UInt16 struct.
  • Os membros de int são os membros da System.Int32 estrutura.The members of int are the members of the System.Int32 struct.
  • Os membros de uint são os membros da System.UInt32 estrutura.The members of uint are the members of the System.UInt32 struct.
  • Os membros de long são os membros da System.Int64 estrutura.The members of long are the members of the System.Int64 struct.
  • Os membros de ulong são os membros da System.UInt64 estrutura.The members of ulong are the members of the System.UInt64 struct.
  • Os membros de char são os membros da System.Char estrutura.The members of char are the members of the System.Char struct.
  • Os membros de float são os membros da System.Single estrutura.The members of float are the members of the System.Single struct.
  • Os membros de double são os membros da System.Double estrutura.The members of double are the members of the System.Double struct.
  • Os membros de decimal são os membros da System.Decimal estrutura.The members of decimal are the members of the System.Decimal struct.
  • Os membros de bool são os membros da System.Boolean estrutura.The members of bool are the members of the System.Boolean struct.

Membros de enumeraçãoEnumeration members

Os membros de uma enumeração são as constantes declaradas na enumeração e os membros herdados da classe base direta da enumeração System.Enum e as classes base indiretas System.ValueType e 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.

Membros de classeClass members

Os membros de uma classe são os membros declarados na classe e os membros herdados da classe base (exceto para object a classe que não tem nenhuma classe 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). Os membros herdados da classe base incluem as constantes, os campos, os métodos, as propriedades, os eventos, os indexadores, os operadores e os tipos da classe base, mas não os construtores de instância, destruidores e construtores estáticos da classe 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. Os membros da classe base são herdados sem considerar sua acessibilidade.Base class members are inherited without regard to their accessibility.

Uma declaração de classe pode conter declarações de constantes, campos, métodos, propriedades, eventos, indexadores, operadores, construtores de instância, destruidores, construtores e tipos estáticos.A class declaration may contain declarations of constants, fields, methods, properties, events, indexers, operators, instance constructors, destructors, static constructors and types.

Os membros de object e string correspondem diretamente aos membros dos tipos de classe que eles alias:The members of object and string correspond directly to the members of the class types they alias:

  • Os membros de object são os membros da System.Object classe.The members of object are the members of the System.Object class.
  • Os membros de string são os membros da System.String classe.The members of string are the members of the System.String class.

Membros da interfaceInterface members

Os membros de uma interface são os membros declarados na interface e em todas as interfaces base da interface.The members of an interface are the members declared in the interface and in all base interfaces of the interface. Os membros da classe object não são, estritamente falando, membros de qualquer interface (membros da interface).The members in class object are not, strictly speaking, members of any interface (Interface members). No entanto, os membros da classe object estão disponíveis por meio de pesquisa de membros em qualquer tipo de interface (pesquisa de membros).However, the members in class object are available via member lookup in any interface type (Member lookup).

Membros de matrizArray members

Os membros de uma matriz são os membros herdados da classe System.Array .The members of an array are the members inherited from class System.Array.

Delegar MembrosDelegate members

Os membros de um delegado são os membros herdados da classe System.Delegate .The members of a delegate are the members inherited from class System.Delegate.

Acesso de membrosMember access

Declarações de Membros permitem o controle sobre o acesso de membro.Declarations of members allow control over member access. A acessibilidade de um membro é estabelecida pela acessibilidade declarada (acessibilidade declarada) do membro combinado com a acessibilidade do tipo que o contém imediatamente, se houver.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.

Quando o acesso a um membro específico é permitido, o membro é considerado *acessível _.When access to a particular member is allowed, the member is said to be *accessible _. Por outro lado, quando o acesso a um determinado membro não é permitido, o membro é considerado _ inacessível *.Conversely, when access to a particular member is disallowed, the member is said to be _*inaccessible**. O acesso a um membro é permitido quando o local textual no qual o acesso ocorre está incluído no domínio de acessibilidade (domínios de acessibilidade) do membro.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.

Acessibilidade declaradaDeclared accessibility

A acessibilidade declarada de um membro pode ser uma das seguintes:The declared accessibility of a member can be one of the following:

  • Public, que é selecionado incluindo um public modificador na declaração de membro.Public, which is selected by including a public modifier in the member declaration. O significado intuitivo de public é "acesso não limitado".The intuitive meaning of public is "access not limited".
  • Protegido, que é selecionado incluindo um protected modificador na declaração de membro.Protected, which is selected by including a protected modifier in the member declaration. O significado intuitivo de protected é "acesso limitado à classe que a contém ou tipos derivados da classe que a contém".The intuitive meaning of protected is "access limited to the containing class or types derived from the containing class".
  • Interno, que é selecionado incluindo um internal modificador na declaração de membro.Internal, which is selected by including an internal modifier in the member declaration. O significado intuitivo de internal é "acesso limitado a este programa".The intuitive meaning of internal is "access limited to this program".
  • Protegido interno (ou seja, protegido ou interno), que é selecionado incluindo um protected e um internal modificador na declaração de membro.Protected internal (meaning protected or internal), which is selected by including both a protected and an internal modifier in the member declaration. O significado intuitivo de protected internal é "acesso limitado a este programa ou tipos derivados da classe que a contém".The intuitive meaning of protected internal is "access limited to this program or types derived from the containing class".
  • Privado, que é selecionado incluindo um private modificador na declaração de membro.Private, which is selected by including a private modifier in the member declaration. O significado intuitivo de private é "acesso limitado ao tipo recipiente".The intuitive meaning of private is "access limited to the containing type".

Dependendo do contexto no qual uma declaração de membro ocorre, somente determinados tipos de acessibilidade declarada são permitidos.Depending on the context in which a member declaration takes place, only certain types of declared accessibility are permitted. Além disso, quando uma declaração de membro não inclui nenhum modificador de acesso, o contexto no qual a declaração ocorre determina a acessibilidade declarada padrão.Furthermore, when a member declaration does not include any access modifiers, the context in which the declaration takes place determines the default declared accessibility.

  • Os namespaces implicitamente public declararam acessibilidade.Namespaces implicitly have public declared accessibility. Nenhum modificador de acesso é permitido em declarações de namespace.No access modifiers are allowed on namespace declarations.
  • Tipos declarados em unidades de compilação ou namespaces podem ter public ou internal declarar acessibilidade e padrão para a internal acessibilidade declarada.Types declared in compilation units or namespaces can have public or internal declared accessibility and default to internal declared accessibility.
  • Os membros de classe podem ter qualquer um dos cinco tipos de acessibilidade declarada e o padrão para a private acessibilidade declarada.Class members can have any of the five kinds of declared accessibility and default to private declared accessibility. (Observe que um tipo declarado como membro de uma classe pode ter qualquer um dos cinco tipos de acessibilidade declarada, enquanto um tipo declarado como membro de um namespace pode ter apenas public ou internal declarado acessibilidade.)(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.)
  • Os membros de struct podem ter public , internal ou private a acessibilidade declarada e o padrão para a private acessibilidade declarada porque as estruturas são lacradas implicitamente.Struct members can have public, internal, or private declared accessibility and default to private declared accessibility because structs are implicitly sealed. Membros de struct introduzidos em uma struct (ou seja, não herdados por essa struct) não podem ter protected ou protected internal declarar acessibilidade.Struct members introduced in a struct (that is, not inherited by that struct) cannot have protected or protected internal declared accessibility. (Observe que um tipo declarado como membro de uma struct pode ter public , internal ou private a acessibilidade declarada, enquanto um tipo declarado como membro de um namespace pode ter apenas public ou internal declarado a acessibilidade.)(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.)
  • Os membros da interface implicitamente public declararam acessibilidade.Interface members implicitly have public declared accessibility. Nenhum modificador de acesso é permitido em declarações de membro de interface.No access modifiers are allowed on interface member declarations.
  • Membros de enumeração implicitamente public declararam acessibilidade.Enumeration members implicitly have public declared accessibility. Nenhum modificador de acesso é permitido em declarações de membro de enumeração.No access modifiers are allowed on enumeration member declarations.

Domínios de acessibilidadeAccessibility domains

O *domínio de acessibilidade _ de um membro consiste nas seções (possivelmente disjunção) do texto do programa no qual o acesso ao membro é permitido.The *accessibility domain _ of a member consists of the (possibly disjoint) sections of program text in which access to the member is permitted. Para fins de definição do domínio de acessibilidade de um membro, um membro será considerado de nível superior se ele não for declarado dentro de um tipo, e um membro será considerado aninhado se for declarado dentro de outro 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. Além disso, o texto do programa de um programa é definido como todo o texto do programa contido em todos os arquivos de origem do programa, e o texto do programa de um tipo é definido como todo o texto do programa contido no _type_declaration * s desse tipo (incluindo, possivelmente, tipos aninhados dentro do 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_declaration*s of that type (including, possibly, types that are nested within the type).

O domínio de acessibilidade de um tipo predefinido (como object , int ou double ) é ilimitado.The accessibility domain of a predefined type (such as object, int, or double) is unlimited.

O domínio de acessibilidade de um tipo não associado de nível superior T (tipos vinculados e desvinculados) que é declarado em um programa P é definido da seguinte maneira: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:

  • Se a acessibilidade declarada do T for public , o domínio de acessibilidade do T é o texto do programa P e qualquer programa que faça referência P a ele.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.
  • Se a acessibilidade declarada de T for internal, o domínio de acessibilidade de T será o 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 dessas definições, a seguir, o domínio de acessibilidade de um tipo não associado de nível superior é sempre pelo menos o texto do programa do programa no qual esse tipo é declarado.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.

O domínio de acessibilidade para um tipo construído T<A1, ..., An> é a interseção do domínio de acessibilidade do tipo genérico não associado T e os domínios de acessibilidade dos 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.

O domínio de acessibilidade de um membro aninhado M declarado em um tipo T dentro de um programa P é definido da seguinte maneira (observando que M ele pode possivelmente ser um 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):

  • Se a acessibilidade declarada de M for public, o domínio de acessibilidade de M será o domínio de acessibilidade de T.If the declared accessibility of M is public, the accessibility domain of M is the accessibility domain of T.
  • Se a acessibilidade declarada de M for protected internal , permita que D seja a União do texto do programa P e o texto do programa de qualquer tipo derivado de T , que é declarado fora do 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. O domínio de acessibilidade do M é a interseção do domínio de acessibilidade do T com o D .The accessibility domain of M is the intersection of the accessibility domain of T with D.
  • Se a acessibilidade declarada M for protected , deixe que D seja a União do texto do programa T e o texto do programa de qualquer 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. O domínio de acessibilidade do M é a interseção do domínio de acessibilidade do T com o D .The accessibility domain of M is the intersection of the accessibility domain of T with D.
  • Se a acessibilidade declarada de M for internal, o domínio de acessibilidade de M será a interseção do domínio de acessibilidade de T com o 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.
  • Se a acessibilidade declarada de M for private, o domínio de acessibilidade de M será o 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 dessas definições, a seguir, o domínio de acessibilidade de um membro aninhado é sempre pelo menos o texto do programa do tipo no qual o membro é declarado.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. Além disso, ele segue que o domínio de acessibilidade de um membro nunca é mais inclusivo do que o domínio de acessibilidade do tipo no qual o membro é declarado.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.

Em termos intuitivos, quando um tipo ou membro M é acessado, as etapas a seguir são avaliadas para garantir que o acesso seja permitido:In intuitive terms, when a type or member M is accessed, the following steps are evaluated to ensure that the access is permitted:

  • Primeiro, se M for declarado dentro de um tipo (em oposição a uma unidade de compilação ou um namespace), ocorrerá um erro de tempo de compilação se esse tipo não estiver acessível.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.
  • Em seguida, se M for public , o acesso será permitido.Then, if M is public, the access is permitted.
  • Caso contrário, se M for protected internal , o acesso será permitido se ocorrer dentro do programa em que M é declarado ou se ocorrer dentro de uma classe derivada da classe em que M é declarada e ocorre por meio do tipo de classe derivada (acesso protegido para membros da instância).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).
  • Caso contrário, se M for protected , o acesso será permitido se ocorrer dentro da classe em que M é declarado, ou se ocorrer dentro de uma classe derivada da classe em que M é declarada e ocorre por meio do tipo de classe derivada (acesso protegido para membros da instância).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).
  • Caso contrário, se M for internal , o acesso será permitido se ocorrer dentro do programa em que M é declarado.Otherwise, if M is internal, the access is permitted if it occurs within the program in which M is declared.
  • Caso contrário, se M for private , o acesso será permitido se ocorrer dentro do tipo em que M é declarado.Otherwise, if M is private, the access is permitted if it occurs within the type in which M is declared.
  • Caso contrário, o tipo ou o membro será inacessível e ocorrerá um erro em tempo de compilação.Otherwise, the type or member is inaccessible, and a compile-time error occurs.

No exemploIn 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;
    }
}

as classes e os membros têm os seguintes domínios de acessibilidade:the classes and members have the following accessibility domains:

  • O domínio de acessibilidade de A e A.X é ilimitado.The accessibility domain of A and A.X is unlimited.
  • O domínio de acessibilidade do,,,,, A.Y B B.X B.Y B.C B.C.X e B.C.Y é o texto do programa do programa que o contém.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.
  • O domínio de acessibilidade do A.Z é o texto do programa do A .The accessibility domain of A.Z is the program text of A.
  • O domínio de acessibilidade do B.Z e B.D é o texto do programa do B , incluindo o texto do programa de B.C e 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.
  • O domínio de acessibilidade do B.C.Z é o texto do programa do B.C .The accessibility domain of B.C.Z is the program text of B.C.
  • O domínio de acessibilidade do B.D.X e B.D.Y é o texto do programa do B , incluindo o texto do programa de B.C e 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.
  • O domínio de acessibilidade do B.D.Z é o texto do programa do B.D .The accessibility domain of B.D.Z is the program text of B.D.

Como ilustra o exemplo, o domínio de acessibilidade de um membro nunca é maior que o de um tipo recipiente.As the example illustrates, the accessibility domain of a member is never larger than that of a containing type. Por exemplo, embora todos os X Membros tenham acessibilidade declarada pública, todos, mas A.X têm domínios de acessibilidade restritos por um tipo recipiente.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.

Conforme descrito em Membros, todos os membros de uma classe base, exceto para construtores de instância, destruidores e construtores estáticos, são herdados por 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. Isso inclui até membros privados de uma classe base.This includes even private members of a base class. No entanto, o domínio de acessibilidade de um membro privado inclui apenas o texto do programa do tipo no qual o membro é declarado.However, the accessibility domain of a private member includes only the program text of the type in which the member is declared. No exemploIn 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
    }
}

a B classe herda o membro privado x da A classe.the B class inherits the private member x from the A class. Como o membro é privado, ele só pode ser acessado dentro do class_body de A .Because the member is private, it is only accessible within the class_body of A. Assim, o acesso a é b.x bem-sucedida no A.F método, mas falha no B.F método.Thus, the access to b.x succeeds in the A.F method, but fails in the B.F method.

Acesso protegido para membros de instânciaProtected access for instance members

Quando um protected membro de instância é acessado fora do texto do programa da classe na qual ele é declarado e quando um protected internal membro da instância é acessado fora do texto do programa no qual ele é declarado, o acesso deve ocorrer dentro de uma declaração de classe que deriva da classe na qual ele é declarado.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. Além disso, o acesso é necessário para ocorrer por meio de uma instância desse tipo de classe derivada ou um tipo de classe construído a partir dele.Furthermore, the access is required to take place through an instance of that derived class type or a class type constructed from it. Essa restrição impede que uma classe derivada acesse membros protegidos de outras classes derivadas, mesmo quando os membros são herdados da mesma classe 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 seja uma classe base que declare um membro de instância protegida M e que D seja uma classe derivada 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 do class_body de D , o acesso ao M pode ter um dos seguintes formatos:Within the class_body of D, access to M can take one of the following forms:

  • Um type_name ou primary_expression não qualificado do formulário M .An unqualified type_name or primary_expression of the form M.
  • Uma primary_expression do formulário E.M , desde que o tipo E seja T ou uma classe derivada de T , em que T é o tipo de classe D , ou um tipo de classe construído 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
  • Uma primary_expression do formulário base.M .A primary_expression of the form base.M.

Além dessas formas de acesso, uma classe derivada pode acessar um construtor de instância protegida de uma classe base em um constructor_initializer (inicializadores de Construtor).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).

No exemploIn 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
    }
}

no A , é possível acessar x por meio de instâncias do A e do B , já que, em ambos os casos, o acesso ocorre por meio de uma instância do A ou de uma classe 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. No entanto, no B , não é possível acessar x por meio de uma instância do A , pois A o não 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.

No exemploIn 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";
    }
}

as três atribuições a x são permitidas porque todas elas ocorrem por meio de instâncias de tipos de classe construídas a partir do 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.

Restrições de acessibilidadeAccessibility constraints

Várias construções na linguagem C# exigem que um tipo seja pelo menos como acessível como um membro ou outro tipo.Several constructs in the C# language require a type to be at least as accessible as a member or another type. Um tipo T é considerado, pelo menos, como acessível como membro ou tipo M se o domínio de acessibilidade do T for um superconjunto do domínio de acessibilidade 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. Em outras palavras, T é pelo menos tão acessível quanto M se T estiver acessível em todos os contextos em que o M está acessível.In other words, T is at least as accessible as M if T is accessible in all contexts in which M is accessible.

Existem as seguintes restrições de acessibilidade:The following accessibility constraints exist:

  • A classe base direta de um tipo de classe deve ser, pelo menos, tão acessível quanto o próprio tipo de classe.The direct base class of a class type must be at least as accessible as the class type itself.
  • As interfaces base explícitas de um tipo de interface devem ser, pelo menos, tão acessíveis quanto o próprio tipo de interface.The explicit base interfaces of an interface type must be at least as accessible as the interface type itself.
  • O tipo de retorno e os tipos de parâmetro de um tipo delegado devem ser, pelo menos, tão acessíveis quanto o próprio tipo delegado.The return type and parameter types of a delegate type must be at least as accessible as the delegate type itself.
  • O tipo de uma constante deve ser, pelo menos, tão acessível quanto a própria constante.The type of a constant must be at least as accessible as the constant itself.
  • O tipo de um campo deve ser, pelo menos, tão acessível quanto o próprio campo.The type of a field must be at least as accessible as the field itself.
  • O tipo de retorno e os tipos de parâmetro de um método devem ser, pelo menos, tão acessíveis quanto o próprio método.The return type and parameter types of a method must be at least as accessible as the method itself.
  • O tipo de uma propriedade deve ser, pelo menos, tão acessível quanto a propriedade em si.The type of a property must be at least as accessible as the property itself.
  • O tipo de um evento deve ser, pelo menos, tão acessível quanto o próprio evento.The type of an event must be at least as accessible as the event itself.
  • O tipo e os tipos de parâmetro de um indexador devem ser, pelo menos, tão acessíveis quanto o próprio indexador.The type and parameter types of an indexer must be at least as accessible as the indexer itself.
  • O tipo de retorno e os tipos de parâmetro de um operador devem ser, pelo menos, tão acessíveis quanto o próprio operador.The return type and parameter types of an operator must be at least as accessible as the operator itself.
  • Os tipos de parâmetro de um construtor de instância devem ser pelo menos tão acessíveis quanto o próprio construtor de instância.The parameter types of an instance constructor must be at least as accessible as the instance constructor itself.

No exemploIn the example

class A {...}

public class B: A {...}

a B classe resulta em um erro de tempo de compilação porque A não é pelo menos tão acessível quanto B .the B class results in a compile-time error because A is not at least as accessible as B.

Da mesma forma, no exemploLikewise, in the example

class A {...}

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

    internal A G() {...}

    public A H() {...}
}

o H método em B resulta em um erro de tempo de compilação porque o tipo de retorno A não é pelo menos tão acessível quanto o 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.

Assinaturas e sobrecargaSignatures and overloading

Os métodos, construtores de instância, indexadores e operadores são caracterizados por suas assinaturas:Methods, instance constructors, indexers, and operators are characterized by their signatures:

  • A assinatura de um método consiste no nome do método, no número de parâmetros de tipo e no tipo e tipo (valor, referência ou saída) de cada um de seus parâmetros formais, considerados na ordem da esquerda para a direita.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 essas finalidades, qualquer parâmetro de tipo do método que ocorre no tipo de um parâmetro formal é identificado não por seu nome, mas por sua posição ordinal na lista de argumentos de tipo do 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. A assinatura de um método especificamente não inclui o tipo de retorno, o params modificador que pode ser especificado para o parâmetro mais à direita, nem as restrições 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.
  • A assinatura de um construtor de instância consiste no tipo e tipo (valor, referência ou saída) de cada um de seus parâmetros formais, considerados na ordem da esquerda para a direita.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. A assinatura de um construtor de instância especificamente não inclui o params modificador que pode ser especificado para o parâmetro mais à direita.The signature of an instance constructor specifically does not include the params modifier that may be specified for the right-most parameter.
  • A assinatura de um indexador consiste no tipo de cada um de seus parâmetros formais, considerados na ordem da esquerda para a direita.The signature of an indexer consists of the type of each of its formal parameters, considered in the order left to right. A assinatura de um indexador especificamente não inclui o tipo de elemento, nem inclui o params modificador que pode ser especificado para o parâmetro mais à direita.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.
  • A assinatura de um operador consiste no nome do operador e no tipo de cada um de seus parâmetros formais, considerados na ordem da esquerda para a direita.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. A assinatura de um operador especificamente não inclui o tipo de resultado.The signature of an operator specifically does not include the result type.

As assinaturas são o mecanismo de habilitação para sobrecarga de membros em classes, estruturas e interfaces:Signatures are the enabling mechanism for overloading of members in classes, structs, and interfaces:

  • A sobrecarga de métodos permite que uma classe, estrutura ou interface declare vários métodos com o mesmo nome, desde que suas assinaturas sejam exclusivas nessa classe, struct ou interface.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.
  • A sobrecarga de construtores de instância permite que uma classe ou estrutura declare vários construtores de instância, desde que suas assinaturas sejam exclusivas dentro dessa classe ou estrutura.Overloading of instance constructors permits a class or struct to declare multiple instance constructors, provided their signatures are unique within that class or struct.
  • A sobrecarga de indexadores permite que uma classe, estrutura ou interface declare vários indexadores, desde que suas assinaturas sejam exclusivas nessa classe, struct ou interface.Overloading of indexers permits a class, struct, or interface to declare multiple indexers, provided their signatures are unique within that class, struct, or interface.
  • A sobrecarga de operadores permite que uma classe ou estrutura declare vários operadores com o mesmo nome, desde que suas assinaturas sejam exclusivas dentro dessa classe ou estrutura.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.

Embora out e ref os modificadores de parâmetro sejam considerados parte de uma assinatura, os membros declarados em um único tipo não podem diferir na assinatura exclusivamente por ref e 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. Ocorrerá um erro de tempo de compilação se dois membros forem declarados no mesmo tipo com assinaturas que seriam as mesmas se todos os parâmetros nos dois métodos com out modificadores fossem alterados para ref modificadores.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 outras finalidades de correspondência de assinatura (por exemplo, ocultar ou substituir) ref e out são consideradas parte da assinatura e não coincidem entre si.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. (Essa restrição é permitir que programas em C# sejam facilmente convertidos para serem executados no Common Language Infrastructure (CLI), que não fornece uma maneira de definir métodos que diferem somente em ref e 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.)

Para os fins de assinaturas, os tipos object e dynamic são considerados iguais.For the purposes of signatures, the types object and dynamic are considered the same. Os membros declarados em um único tipo podem, portanto, não ser diferentes na assinatura exclusivamente pelo object e dynamic .Members declared in a single type can therefore not differ in signature solely by object and dynamic.

O exemplo a seguir mostra um conjunto de declarações de método sobrecarregadas junto com suas assinaturas.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
}

Observe que quaisquer ref out modificadores de parâmetro e (parâmetros de método) fazem parte de uma assinatura.Note that any ref and out parameter modifiers (Method parameters) are part of a signature. Portanto, F(int) e F(ref int) são assinaturas exclusivas.Thus, F(int) and F(ref int) are unique signatures. No entanto, F(ref int) e F(out int) não podem ser declarados na mesma interface porque suas assinaturas diferem exclusivamente por ref e 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. Além disso, observe que o tipo de retorno e o params modificador não fazem parte de uma assinatura, portanto, não é possível sobrecarregar unicamente com base no tipo de retorno ou na inclusão ou exclusão do params modificador.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, as declarações dos métodos F(int) e F(params string[]) identificadas acima resultam em um erro de tempo de compilação.As such, the declarations of the methods F(int) and F(params string[]) identified above result in a compile-time error.

EscoposScopes

O *escopo _ de um nome é a região do texto do programa no qual é possível fazer referência à entidade declarada pelo nome sem qualificação do nome.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. Os escopos podem ser aninhados, e um escopo interno pode redeclarar o significado de um nome a partir de um escopo externo (isso não, no entanto, remover a restrição imposta por declarações que dentro de um bloco aninhado não é possível declarar uma variável local com o mesmo nome que uma variável local em um bloco delimitador).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). O nome do escopo externo, em seguida, é dito como _ Hidden* na região do texto do programa coberto pelo escopo interno, e o acesso ao nome externo só é possível qualificando o nome.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.

  • O escopo de um membro de namespace declarado por um namespace_member_declaration (membros de namespace) sem delimitador namespace_declaration é o texto completo do 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.
  • O escopo de um membro de namespace declarado por um namespace_member_declaration dentro de um namespace_declaration cujo nome totalmente qualificado é N a namespace_body de cada namespace_declaration cujo nome totalmente qualificado é N ou começa com N , seguido por um ponto.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.
  • O escopo do nome definido por uma extern_alias_directive se estende sobre os using_directive s, global_attributes e namespace_member_declaration s de seu logo contendo a unidade de compilação ou o corpo do namespace.The scope of name defined by an extern_alias_directive extends over the using_directive s, global_attributes and namespace_member_declaration s of its immediately containing compilation unit or namespace body. Um extern_alias_directive não contribui com nenhum novo membro para o espaço de declaração subjacente.An extern_alias_directive does not contribute any new members to the underlying declaration space. Em outras palavras, um extern_alias_directive não é transitiva, mas, em vez disso, afeta apenas a unidade de compilação ou o corpo do namespace no qual ele ocorre.In other words, an extern_alias_directive is not transitive, but, rather, affects only the compilation unit or namespace body in which it occurs.
  • O escopo de um nome definido ou importado por um using_directive (usando diretivas) se estende sobre os namespace_member_declaration s do compilation_unit ou namespace_body em que a using_directive ocorre.The scope of a name defined or imported by a using_directive (Using directives) extends over the namespace_member_declaration s of the compilation_unit or namespace_body in which the using_directive occurs. Uma using_directive pode tornar zero ou mais nomes de namespace, tipo ou membro disponíveis em um compilation_unit ou namespace_body específico, mas não contribui com novos membros para o espaço de declaração subjacente.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. Em outras palavras, um using_directive não é transitiva, mas, em vez disso, afeta apenas o compilation_unit ou namespace_body em que ele ocorre.In other words, a using_directive is not transitive but rather affects only the compilation_unit or namespace_body in which it occurs.
  • O escopo de um parâmetro de tipo declarado por um type_parameter_list em um class_declaration (declarações de classe) é o class_base, type_parameter_constraints_clause s e class_body do 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_clause s, and class_body of that class_declaration.
  • O escopo de um parâmetro de tipo declarado por um type_parameter_list em um struct_declaration (declarações struct) é o struct_interfaces, type_parameter_constraints_clause s e struct_body do 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_clause s, and struct_body of that struct_declaration.
  • O escopo de um parâmetro de tipo declarado por um type_parameter_list em um interface_declaration (declarações de interface) é o interface_base, type_parameter_constraints_clause s e interface_body do 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_clause s, and interface_body of that interface_declaration.
  • O escopo de um parâmetro de tipo declarado por um type_parameter_list em um delegate_declaration (declarações de delegado) é o return_type, formal_parameter_list e type_parameter_constraints_clause s do 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_clause s of that delegate_declaration.
  • O escopo de um membro declarado por um class_member_declaration (corpo de classe) é a class_body na qual a declaração ocorre.The scope of a member declared by a class_member_declaration (Class body) is the class_body in which the declaration occurs. Além disso, o escopo de um membro de classe se estende à class_body dessas classes derivadas que são incluídas no domínio de acessibilidade (domínios de acessibilidade) do membro.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.
  • O escopo de um membro declarado por um struct_member_declaration (membros de struct) é a struct_body na qual a declaração ocorre.The scope of a member declared by a struct_member_declaration (Struct members) is the struct_body in which the declaration occurs.
  • O escopo de um membro declarado por um enum_member_declaration (membros de enumeração) é o enum_body no qual a declaração ocorre.The scope of a member declared by an enum_member_declaration (Enum members) is the enum_body in which the declaration occurs.
  • O escopo de um parâmetro declarado em um method_declaration (métodos) é a method_body do method_declaration.The scope of a parameter declared in a method_declaration (Methods) is the method_body of that method_declaration.
  • O escopo de um parâmetro declarado em um indexer_declaration (indexadores) é o accessor_declarations do indexer_declaration.The scope of a parameter declared in an indexer_declaration (Indexers) is the accessor_declarations of that indexer_declaration.
  • O escopo de um parâmetro declarado em um operator_declaration (Operators) é o bloco desse operator_declaration.The scope of a parameter declared in an operator_declaration (Operators) is the block of that operator_declaration.
  • O escopo de um parâmetro declarado em um constructor_declaration (construtores de instância) é o constructor_initializer e o bloco desse constructor_declaration.The scope of a parameter declared in a constructor_declaration (Instance constructors) is the constructor_initializer and block of that constructor_declaration.
  • O escopo de um parâmetro declarado em uma lambda_expression (expressões de função anônimas) é o anonymous_function_body do lambda_expressionThe scope of a parameter declared in a lambda_expression (Anonymous function expressions) is the anonymous_function_body of that lambda_expression
  • O escopo de um parâmetro declarado em uma anonymous_method_expression (expressões de função anônimas) é o bloco desse 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.
  • O escopo de um rótulo declarado em um labeled_statement (instruções rotuladas) é o bloco no qual a declaração ocorre.The scope of a label declared in a labeled_statement (Labeled statements) is the block in which the declaration occurs.
  • O escopo de uma variável local declarada em uma local_variable_declaration (declarações de variável local) é o bloco no qual a declaração ocorre.The scope of a local variable declared in a local_variable_declaration (Local variable declarations) is the block in which the declaration occurs.
  • O escopo de uma variável local declarada em uma switch_block de uma switch instrução (a instrução switch) é a switch_block.The scope of a local variable declared in a switch_block of a switch statement (The switch statement) is the switch_block.
  • O escopo de uma variável local declarada em uma for_initializer de uma for instrução (a instrução for) é a for_initializer, a for_condition, a for_iterator e a instrução contida da for instrução.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.
  • O escopo de uma constante local declarada em uma local_constant_declaration (declarações de constantes locais) é o bloco no qual a declaração ocorre.The scope of a local constant declared in a local_constant_declaration (Local constant declarations) is the block in which the declaration occurs. É um erro de tempo de compilação para se referir a uma constante local em uma posição textual que precede seu constant_declarator.It is a compile-time error to refer to a local constant in a textual position that precedes its constant_declarator.
  • O escopo de uma variável declarada como parte de um foreach_statement, using_statement, lock_statement ou query_expression é determinado pela expansão da construção fornecida.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 do escopo de um namespace, classe, struct ou membro de enumeração, é possível fazer referência ao membro em uma posição textual que precede a declaração do membro.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 exemplo,For example

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

    int i = 0;
}

Aqui, é válido para F que o faça referência i antes de ser declarado.Here, it is valid for F to refer to i before it is declared.

Dentro do escopo de uma variável local, é um erro de tempo de compilação para se referir à variável local em uma posição textual que precede a local_variable_declarator da variável 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 exemplo,For 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
    }
}

No F método acima, a primeira atribuição para i especificamente não se refere ao campo declarado no escopo externo.In the F method above, the first assignment to i specifically does not refer to the field declared in the outer scope. Em vez disso, ele se refere à variável local e resulta em um erro de tempo de compilação porque ele precede textualmente a declaração da variável.Rather, it refers to the local variable and it results in a compile-time error because it textually precedes the declaration of the variable. No G método, o uso de j no inicializador para a declaração de j é válido porque o uso não 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. No H método, um local_variable_declarator subsequentemente se refere a uma variável local declarada em um local_variable_declarator anterior dentro do mesmo 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.

As regras de escopo para variáveis locais são projetadas para garantir que o significado de um nome usado em um contexto de expressão seja sempre o mesmo dentro de um bloco.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. Se o escopo de uma variável local fosse estender apenas de sua declaração para o final do bloco, no exemplo acima, a primeira atribuição seria atribuída à variável de instância e a segunda atribuição seria atribuída à variável local, possivelmente levando a erros de tempo de compilação se as instruções do bloco fossem posteriormente reorganizadas.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.

O significado de um nome dentro de um bloco pode ser diferente com base no contexto no qual o nome é usado.The meaning of a name within a block may differ based on the context in which the name is used. No exemploIn 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"
    }
}

o nome A é usado em um contexto de expressão para se referir à variável local A e em um contexto de tipo para fazer referência à classe 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.

Ocultação de nomesName hiding

O escopo de uma entidade normalmente abrange mais texto de programa do que o espaço de declaração da entidade.The scope of an entity typically encompasses more program text than the declaration space of the entity. Em particular, o escopo de uma entidade pode incluir declarações que apresentam novos espaços de declaração contendo entidades de mesmo nome.In particular, the scope of an entity may include declarations that introduce new declaration spaces containing entities of the same name. Tais declarações fazem com que a entidade original se torne *Hidden _.Such declarations cause the original entity to become *hidden _. Por outro lado, uma entidade é considerada _ visível* quando não está oculta.Conversely, an entity is said to be _ visible* when it is not hidden.

A ocultação de nome ocorre quando os escopos se sobrepõem no aninhamento e quando os escopos se sobrepõem pela herançaName hiding occurs when scopes overlap through nesting and when scopes overlap through inheritance. As características dos dois tipos de ocultação são descritas nas seções a seguir.The characteristics of the two types of hiding are described in the following sections.

Ocultando por meio de aninhamentoHiding through nesting

O nome que oculta o aninhamento pode ocorrer como resultado de aninhar namespaces ou tipos dentro de namespaces, como resultado de aninhar tipos dentro de classes ou estruturas, e como resultado de declarações de parâmetro e variável local.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.

No exemploIn the example

class A
{
    int i = 0;

    void F() {
        int i = 1;
    }

    void G() {
        i = 1;
    }
}

dentro do F método, a variável de instância i é ocultada pela variável local i , mas dentro do G método, i ainda se refere à variável de instância.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.

Quando um nome em um escopo interno oculta um nome em um escopo externo, ele oculta todas as ocorrências sobrecarregadas desse nome.When a name in an inner scope hides a name in an outer scope, it hides all overloaded occurrences of that name. No exemploIn 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) {}
    }
}

a chamada F(1) invoca o F declarado em Inner porque todas as ocorrências externas de F são ocultadas pela declaração interna.the call F(1) invokes the F declared in Inner because all outer occurrences of F are hidden by the inner declaration. Pelo mesmo motivo, a chamada F("Hello") resulta em um erro de tempo de compilação.For the same reason, the call F("Hello") results in a compile-time error.

Ocultando por meio de herançaHiding through inheritance

O nome que se oculta pela herança ocorre quando as classes ou estruturas redeclaram nomes que foram herdados de classes base.Name hiding through inheritance occurs when classes or structs redeclare names that were inherited from base classes. Esse tipo de ocultação de nome usa uma das seguintes formas:This type of name hiding takes one of the following forms:

  • Uma constante, campo, propriedade, evento ou tipo introduzido em uma classe ou struct oculta todos os membros da classe base com o mesmo nome.A constant, field, property, event, or type introduced in a class or struct hides all base class members with the same name.
  • Um método introduzido em uma classe ou struct oculta todos os membros da classe base que não são de método com o mesmo nome e todos os métodos da classe base com a mesma assinatura (nome do método e contagem de parâmetros, modificadores e 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).
  • Um indexador introduzido em uma classe ou estrutura oculta todos os indexadores de classe base com a mesma assinatura (contagem de parâmetros e tipos).An indexer introduced in a class or struct hides all base class indexers with the same signature (parameter count and types).

As regras que regem as declarações de operador (operadores) tornam impossível para uma classe derivada declarar um operador com a mesma assinatura de um operador em uma classe 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. Portanto, os operadores nunca ocultam um ao outro.Thus, operators never hide one another.

Ao contrário de ocultar um nome de um escopo externo, ocultar um nome acessível de um escopo herdado faz com que um aviso seja relatado.Contrary to hiding a name from an outer scope, hiding an accessible name from an inherited scope causes a warning to be reported. No exemploIn the example

class Base
{
    public void F() {}
}

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

a declaração de F no Derived faz com que um aviso seja relatado.the declaration of F in Derived causes a warning to be reported. Ocultar um nome herdado não é especificamente um erro, já que isso impediria uma evolução separada das classes base.Hiding an inherited name is specifically not an error, since that would preclude separate evolution of base classes. Por exemplo, a situação acima pode ter surgido porque uma versão posterior do Base introduziu um F método que não estava presente em uma versão anterior da classe.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. Se houvesse um erro na situação acima, qualquer alteração feita em uma classe base em uma biblioteca de classes com controle de versão separada poderia potencialmente fazer com que as classes derivadas se tornassem invá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.

O aviso causado pela ocultação de um nome herdado pode ser eliminado por meio do uso do new modificador: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() {}
}

O new modificador indica que o F no Derived é "New", e que realmente se destina a ocultar o membro herdado.The new modifier indicates that the F in Derived is "new", and that it is indeed intended to hide the inherited member.

Uma declaração de um novo membro oculta um membro herdado somente dentro do escopo do novo membro.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
}

No exemplo acima, a declaração de F em Derived oculta o F que foi herdado de Base , mas como o novo F no Derived tem acesso privado, seu escopo não se estende para 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. Portanto, a chamada F() em MoreDerived.G é válida e será invocada Base.F .Thus, the call F() in MoreDerived.G is valid and will invoke Base.F.

Namespace e nomes de tiposNamespace and type names

Vários contextos em um programa C# exigem um Namespace_Name ou um type_name ser especificado.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
    ;

Uma Namespace_Name é uma namespace_or_type_name que se refere a um namespace.A namespace_name is a namespace_or_type_name that refers to a namespace. Após a resolução, conforme descrito abaixo, a namespace_or_type_name de um Namespace_Name deve se referir a um namespace ou, caso contrário, ocorrerá um erro de tempo de compilação.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. Nenhum argumento de tipo (argumentos de tipo) pode estar presente em um Namespace_Name (somente tipos podem ter argumentos de tipo).No type arguments (Type arguments) can be present in a namespace_name (only types can have type arguments).

Uma type_name é uma namespace_or_type_name que se refere a um tipo.A type_name is a namespace_or_type_name that refers to a type. Após a resolução, conforme descrito abaixo, a namespace_or_type_name de um type_name deve se referir a um tipo ou, caso contrário, ocorrerá um erro de tempo de compilação.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.

Se o namespace_or_type_name for um membro de alias qualificado, seu significado será conforme descrito em qualificadores de alias de namespace.If the namespace_or_type_name is a qualified-alias-member its meaning is as described in Namespace alias qualifiers. Caso contrário, um namespace_or_type_name tem uma das quatro formas:Otherwise, a namespace_or_type_name has one of four forms:

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

onde I é um único identificador, N é um namespace_or_type_name e <A1, ..., Ak> é um type_argument_list opcional.where I is a single identifier, N is a namespace_or_type_name and <A1, ..., Ak> is an optional type_argument_list. Quando nenhum type_argument_list for especificado, considere k ser zero.When no type_argument_list is specified, consider k to be zero.

O significado de um namespace_or_type_name é determinado da seguinte maneira:The meaning of a namespace_or_type_name is determined as follows:

  • Se a namespace_or_type_name estiver no formato I ou no formato I<A1, ..., Ak> :If the namespace_or_type_name is of the form I or of the form I<A1, ..., Ak>:
    • Se K for zero e o namespace_or_type_name aparecer dentro de uma declaração de método genérico (métodos) e se essa declaração incluir um parâmetro de tipo (parâmetros de tipo) com  I o nome, o namespace_or_type_name se referirá a esse 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.
    • Caso contrário, se o namespace_or_type_name aparecer dentro de uma declaração de tipo, para cada tipo de instância  T (o tipo de instância), começando com o tipo de instância dessa declaração de tipo e continuando com o tipo de instância de cada classe de delimitadora ou declaração struct (se houver):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):
      • Se K for zero e a declaração de T incluir um parâmetro de tipo com  I o nome, o namespace_or_type_name se referirá a esse 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.
      • Caso contrário, se o namespace_or_type_name aparecer dentro do corpo da declaração de tipo, e T ou qualquer um de seus tipos base contiver um tipo acessível aninhado com  I parâmetros de nome e K   tipo, então o namespace_or_type_name se referirá a esse tipo construído com os argumentos de tipo fornecidos.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. Se houver mais de um tipo, o tipo declarado dentro do tipo mais derivado será selecionado.If there is more than one such type, the type declared within the more derived type is selected. Observe que os membros não tipo (constantes, campos, métodos, propriedades, indexadores, operadores, construtores de instância, destruidores e construtores estáticos) e membros de tipo com um número diferente de parâmetros de tipo são ignorados ao determinar o significado do 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.
    • Se as etapas anteriores não tiverem sido bem-sucedidas, para cada namespace  N , começando com o namespace no qual o namespace_or_type_name ocorre, continuando com cada namespace delimitador (se houver) e terminando com o namespace global, as etapas a seguir são avaliadas até que uma entidade esteja localizada: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:
      • Se K for zero e I for o nome de um namespace em  N , então:If K is zero and I is the name of a namespace in N, then:
        • Se o local onde a namespace_or_type_name ocorre estiver entre uma declaração de namespace para N e a declaração de namespace contiver um extern_alias_directive ou using_alias_directive que associa o nome a  I um namespace ou tipo, o namespace_or_type_name será ambíguo e ocorrerá um erro em tempo de compilação.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.
        • Caso contrário, o namespace_or_type_name se refere ao namespace chamado I em N .Otherwise, the namespace_or_type_name refers to the namespace named I in N.
      • Caso contrário, se N contiver um tipo acessível com  I parâmetros Name e K   Type, então:Otherwise, if N contains an accessible type having name I and K type parameters, then:
        • Se K for zero e o local em que o namespace_or_type_name ocorrer é incluído por uma declaração de namespace para N e a declaração de namespace contém um extern_alias_directive ou using_alias_directive que associa o nome a  I um namespace ou tipo, o namespace_or_type_name é ambíguo e ocorre um erro em tempo de compilação.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.
        • Caso contrário, o namespace_or_type_name se refere ao tipo construído com os argumentos de tipo fornecidos.Otherwise, the namespace_or_type_name refers to the type constructed with the given type arguments.
      • Caso contrário, se o local em que o namespace_or_type_name ocorrer for incluído por uma declaração de namespace para N :Otherwise, if the location where the namespace_or_type_name occurs is enclosed by a namespace declaration for N:
        • Se K for zero e a declaração de namespace contiver um extern_alias_directive ou using_alias_directive que associa o nome a  I um namespace ou tipo importado, a namespace_or_type_name se referirá a esse namespace ou 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.
        • Caso contrário, se os namespaces e as declarações de tipo importados pelo using_namespace_directive s e using_alias_directive s da declaração de namespace contiverem exatamente um tipo acessível  I com parâmetros de nome e K   tipo, a namespace_or_type_name se referirá a esse tipo construído com os argumentos de tipo fornecidos.Otherwise, if the namespaces and type declarations imported by the using_namespace_directive s and using_alias_directive s 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.
        • Caso contrário, se os namespaces e as declarações de tipo importados pelo using_namespace_directive s e using_alias_directive s da declaração de namespace contiverem mais de um tipo acessível com  I parâmetros de nome e K   tipo, a namespace_or_type_name será ambígua e ocorrerá um erro.Otherwise, if the namespaces and type declarations imported by the using_namespace_directive s and using_alias_directive s 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.
    • Caso contrário, o namespace_or_type_name será indefinido e ocorrerá um erro em tempo de compilação.Otherwise, the namespace_or_type_name is undefined and a compile-time error occurs.
  • Caso contrário, a namespace_or_type_name será da forma N.I ou do formulário 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 é resolvido primeiro como um namespace_or_type_name.N is first resolved as a namespace_or_type_name. Se a resolução de N não for bem-sucedida, ocorrerá um erro em tempo de compilação.If the resolution of N is not successful, a compile-time error occurs. Caso contrário, N.I ou N.I<A1, ..., Ak> é resolvido da seguinte maneira:Otherwise, N.I or N.I<A1, ..., Ak> is resolved as follows:
    • Se K for zero e N se referir a um namespace e N contiver um namespace aninhado com name I , o namespace_or_type_name se referirá a esse namespace aninhado.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.
    • Caso contrário, se se N referir a um namespace e N contiver um tipo acessível com  I parâmetros Name e K   Type, o namespace_or_type_name se referirá a esse tipo construído com os argumentos de tipo fornecidos.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.
    • Caso contrário, se N se referir a uma classe (possivelmente construída) ou tipo struct e N ou qualquer uma de suas classes base contiver um tipo acessível aninhado com  I parâmetros Name e K   Type, o namespace_or_type_name se referirá a esse tipo construído com os argumentos de tipo fornecidos.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. Se houver mais de um tipo, o tipo declarado dentro do tipo mais derivado será selecionado.If there is more than one such type, the type declared within the more derived type is selected. Observe que, se o significado de N.I estiver sendo determinado como parte da resolução da especificação da classe base de N , a classe base direta de N será considerada objeto (classes 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).
    • Caso contrário, N.I é um namespace_or_type_name inválido e ocorre um erro em tempo de compilação.Otherwise, N.I is an invalid namespace_or_type_name, and a compile-time error occurs.

Um namespace_or_type_name tem permissão para fazer referência a uma classe estática (classes estáticas) somente seA namespace_or_type_name is permitted to reference a static class (Static classes) only if

  • O namespace_or_type_name é o T em uma namespace_or_type_name do formulário T.I ouThe namespace_or_type_name is the T in a namespace_or_type_name of the form T.I, or
  • O namespace_or_type_name é o T em uma typeof_expression (lista de argumentos1) do formulário typeof(T) .The namespace_or_type_name is the T in a typeof_expression (Argument lists1) of the form typeof(T).

Nomes totalmente qualificadosFully qualified names

Cada namespace e tipo tem um nome totalmente qualificado, que identifica exclusivamente o namespace ou o tipo entre todos os outros.Every namespace and type has a fully qualified name, which uniquely identifies the namespace or type amongst all others. O nome totalmente qualificado de um namespace ou tipo N é determinado da seguinte maneira:The fully qualified name of a namespace or type N is determined as follows:

  • Se N for um membro do namespace global, seu nome totalmente qualificado será N .If N is a member of the global namespace, its fully qualified name is N.
  • Caso contrário, seu nome totalmente qualificado é S.N , em que S é o nome totalmente qualificado do namespace ou tipo no qual N é declarado.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.

Em outras palavras, o nome totalmente qualificado de N é o caminho hierárquico completo dos identificadores que resultam N , começando do namespace 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. Como cada membro de um namespace ou tipo deve ter um nome exclusivo, ele segue que o nome totalmente qualificado de um namespace ou tipo é sempre exclusivo.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.

O exemplo a seguir mostra várias declarações de namespace e tipo junto com seus nomes totalmente qualificados associados.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
}

Gerenciamento automático de memóriaAutomatic memory management

O C# emprega o gerenciamento automático de memória, que libera os desenvolvedores de alocar e liberar manualmente a memória ocupada por objetos.C# employs automatic memory management, which frees developers from manually allocating and freeing the memory occupied by objects. As políticas de gerenciamento automático de memória são implementadas por um coletor de lixo.Automatic memory management policies are implemented by a garbage collector. O ciclo de vida de gerenciamento de memória de um objeto é o seguinte:The memory management life cycle of an object is as follows:

  1. Quando o objeto é criado, a memória é alocada para ele, o construtor é executado e o objeto é considerado dinâmico.When the object is created, memory is allocated for it, the constructor is run, and the object is considered live.
  2. Se o objeto, ou qualquer parte dele, não puder ser acessado por nenhuma possível continuação de execução, além da execução de destruidores, o objeto será considerado não em uso e se tornará elegível para destruição.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. O compilador C# e o coletor de lixo podem optar por analisar o código para determinar quais referências a um objeto podem ser usadas no 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 exemplo, se uma variável local que está no escopo for a única referência existente a um objeto, mas essa variável local nunca for referida em qualquer continuação possível de execução do ponto de execução atual no procedimento, o coletor de lixo pode (mas não é necessário) tratar o objeto como não está mais em 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. Depois que o objeto estiver qualificado para destruição, em algum momento não especificado, o destruidor (destruidores) (se houver) para o objeto será executado.Once the object is eligible for destruction, at some unspecified later time the destructor (Destructors) (if any) for the object is run. Em circunstâncias normais, o destruidor para o objeto é executado apenas uma vez, embora APIs específicas de implementação possam permitir que esse comportamento seja substituído.Under normal circumstances the destructor for the object is run once only, though implementation-specific APIs may allow this behavior to be overridden.
  4. Depois que o destruidor de um objeto for executado, se esse objeto ou qualquer parte dele, não puder ser acessado por qualquer continuação possível de execução, incluindo a execução de destruidores, o objeto será considerado inacessível e o objeto se tornará elegível para a coleta.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. Finalmente, em algum momento depois que o objeto se tornar qualificado para a coleta, o coletor de lixo liberará a memória associada a esse objeto.Finally, at some time after the object becomes eligible for collection, the garbage collector frees the memory associated with that object.

O coletor de lixo mantém informações sobre o uso do objeto e usa essas informações para tomar decisões de gerenciamento de memória, como o local na memória para localizar um objeto recém-criado, quando realocar um objeto e quando um objeto não está mais em uso ou inacessível.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.

Como outras linguagens que assumem a existência de um coletor de lixo, o C# é projetado para que o coletor de lixo possa implementar uma ampla gama de políticas de gerenciamento de memória.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 exemplo, o C# não exige que os destruidores sejam executados ou que os objetos sejam coletados assim que estiverem qualificados ou que os destruidores sejam executados em qualquer ordem específica ou em qualquer thread específico.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.

O comportamento do coletor de lixo pode ser controlado, em algum grau, por meio de métodos estáticos na classe System.GC .The behavior of the garbage collector can be controlled, to some degree, via static methods on the class System.GC. Essa classe pode ser usada para solicitar que uma coleção ocorra, destruidores sejam executados (ou não executados) e assim por diante.This class can be used to request a collection to occur, destructors to be run (or not run), and so forth.

Como o coletor de lixo tem permissão de uma ampla latitude ao decidir quando coletar objetos e executar destruidores, uma implementação de conformidade pode produzir uma saída diferente da mostrada pelo código a seguir.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. O 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();
    }
}

Cria uma instância da classe A e uma instância da classe B .creates an instance of class A and an instance of class B. Esses objetos se tornam qualificados para a coleta de lixo quando a variável b é atribuída ao valor null , já que, após esse tempo, é impossível para qualquer código escrito pelo usuário acessá-los.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. A saída pode serThe output could be either

Destruct instance of A
Destruct instance of B

ouor

Destruct instance of B
Destruct instance of A

Porque o idioma impõe nenhuma restrição na ordem em que os objetos são coletados como lixo.because the language imposes no constraints on the order in which objects are garbage collected.

Em casos sutis, a distinção entre "qualificado para destruição" e "elegível para coleta" pode ser importante.In subtle cases, the distinction between "eligible for destruction" and "eligible for collection" can be important. Por exemplo,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");
    }
}

No programa acima, se o coletor de lixo optar por executar o destruidor de A antes do destruidor de B , a saída desse programa poderá 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

Observe que, embora a instância do A não esteja em uso e o A destruidor fosse executado, ainda é possível que os métodos de A (neste caso, F ) sejam chamados de outro destruidor.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. Além disso, observe que a execução de um destruidor pode fazer com que um objeto se torne utilizável do programa principal novamente.Also, note that running of a destructor may cause an object to become usable from the mainline program again. Nesse caso, a execução do B destruidor causou uma instância do A que não estava em uso anteriormente para tornar-se acessível da referência dinâmica 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. Após a chamada para WaitForPendingFinalizers , a instância do B é elegível para a coleção, mas a instância do A não é, devido à referência 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 confusão e comportamento inesperado, geralmente é uma boa ideia para destruidores apenas realizar a limpeza nos dados armazenados nos próprios campos de seu objeto e não executar ações em objetos referenciados ou em 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.

Uma alternativa ao uso de destruidores é deixar uma classe implementar a System.IDisposable interface.An alternative to using destructors is to let a class implement the System.IDisposable interface. Isso permite que o cliente do objeto determine quando liberar os recursos do objeto, normalmente acessando o objeto como um recurso em uma using instrução (a instrução 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).

Ordem de execuçãoExecution order

A execução de um programa em C# prossegue de forma que os efeitos colaterais de cada thread em execução sejam preservados em pontos de execução críticos.Execution of a C# program proceeds such that the side effects of each executing thread are preserved at critical execution points. Um efeito colateral é definido como uma leitura ou gravação de um campo volátil, uma gravação em uma variável não volátil, uma gravação em um recurso externo e o lançamento de uma exceção.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. Os pontos de execução críticos em que a ordem desses efeitos colaterais devem ser preservados são referências a campos voláteis (campos voláteis), lock instruções (a instrução de bloqueio) e criação e encerramento de threads.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. O ambiente de execução é livre para alterar a ordem de execução de um programa em C#, sujeito às seguintes restrições:The execution environment is free to change the order of execution of a C# program, subject to the following constraints:

  • A dependência de dados é preservada dentro de um thread de execução.Data dependence is preserved within a thread of execution. Ou seja, o valor de cada variável é calculado como se todas as instruções no thread fossem executadas na ordem do programa original.That is, the value of each variable is computed as if all statements in the thread were executed in original program order.
  • As regras de ordenação de inicialização são preservadas (inicialização de campo e inicializadores de variável).Initialization ordering rules are preserved (Field initialization and Variable initializers).
  • A ordenação de efeitos colaterais é preservada em relação às leituras e gravações voláteis (campos voláteis).The ordering of side effects is preserved with respect to volatile reads and writes (Volatile fields). Além disso, o ambiente de execução não precisa avaliar parte de uma expressão se puder deduzir que o valor da expressão não é usado e que nenhum efeito colateral necessário é produzido (incluindo qualquer causado pela chamada de um método ou acesso a um 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). Quando a execução do programa é interrompida por um evento assíncrono (como uma exceção lançada por outro thread), não há garantia de que os efeitos laterais observáveis estão visíveis na ordem do 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.