InstruçõesStatements
O C# fornece uma variedade de instruções.C# provides a variety of statements. A maioria dessas instruções será familiar para os desenvolvedores que se programaram em C e C++.Most of these statements will be familiar to developers who have programmed in C and C++.
statement
: labeled_statement
| declaration_statement
| embedded_statement
;
embedded_statement
: block
| empty_statement
| expression_statement
| selection_statement
| iteration_statement
| jump_statement
| try_statement
| checked_statement
| unchecked_statement
| lock_statement
| using_statement
| yield_statement
| embedded_statement_unsafe
;
O embedded_statement não terminal é usado para instruções que aparecem dentro de outras instruções.The embedded_statement nonterminal is used for statements that appear within other statements. O uso de embedded_statement em vez de instrução exclui o uso de instruções de declaração e instruções rotuladas nesses contextos.The use of embedded_statement rather than statement excludes the use of declaration statements and labeled statements in these contexts. O exemploThe example
void F(bool b) {
if (b)
int i = 44;
}
resulta em um erro de tempo de compilação porque uma if
instrução requer uma embedded_statement em vez de uma instrução para sua ramificação If.results in a compile-time error because an if
statement requires an embedded_statement rather than a statement for its if branch. Se esse código fosse permitido, a variável i
seria declarada, mas nunca poderia ser usada.If this code were permitted, then the variable i
would be declared, but it could never be used. No entanto, observe que, colocando i
a declaração de em um bloco, o exemplo é válido.Note, however, that by placing i
's declaration in a block, the example is valid.
Pontos de extremidade e acessibilidadeEnd points and reachability
Cada instrução tem um ponto de extremidade.Every statement has an end point. Em termos intuitivos, o ponto de extremidade de uma instrução é o local que segue imediatamente a instrução.In intuitive terms, the end point of a statement is the location that immediately follows the statement. As regras de execução para instruções compostas (instruções que contêm instruções inseridas) especificam a ação que é executada quando o controle atinge o ponto de extremidade de uma instrução inserida.The execution rules for composite statements (statements that contain embedded statements) specify the action that is taken when control reaches the end point of an embedded statement. Por exemplo, quando o controle atinge o ponto de extremidade de uma instrução em um bloco, o controle é transferido para a próxima instrução no bloco.For example, when control reaches the end point of a statement in a block, control is transferred to the next statement in the block.
Se uma instrução puder ser alcançada pela execução, a instrução será considerada *alcançável _.If a statement can possibly be reached by execution, the statement is said to be *reachable _. Por outro lado, se não houver nenhuma possibilidade de que uma instrução seja executada, a instrução será considerada _ inacessível *.Conversely, if there is no possibility that a statement will be executed, the statement is said to be _*unreachable**.
No exemploIn the example
void F() {
Console.WriteLine("reachable");
goto Label;
Console.WriteLine("unreachable");
Label:
Console.WriteLine("reachable");
}
a segunda invocação de Console.WriteLine
está inacessível porque não há possibilidade de que a instrução seja executada.the second invocation of Console.WriteLine
is unreachable because there is no possibility that the statement will be executed.
Um aviso será relatado se o compilador determinar que uma instrução está inacessível.A warning is reported if the compiler determines that a statement is unreachable. Especificamente, não é um erro para que uma instrução fique inacessível.It is specifically not an error for a statement to be unreachable.
Para determinar se uma determinada instrução ou ponto de extremidade pode ser acessado, o compilador executa a análise de fluxo de acordo com as regras de acessibilidade definidas para cada instrução.To determine whether a particular statement or end point is reachable, the compiler performs flow analysis according to the reachability rules defined for each statement. A análise de fluxo leva em conta os valores de expressões constantes (expressões constantes) que controlam o comportamento de instruções, mas os valores possíveis de expressões não constantes não são considerados.The flow analysis takes into account the values of constant expressions (Constant expressions) that control the behavior of statements, but the possible values of non-constant expressions are not considered. Em outras palavras, para fins de análise de fluxo de controle, uma expressão não constante de um determinado tipo é considerada com qualquer valor possível desse tipo.In other words, for purposes of control flow analysis, a non-constant expression of a given type is considered to have any possible value of that type.
No exemploIn the example
void F() {
const int i = 1;
if (i == 2) Console.WriteLine("unreachable");
}
a expressão booliana da if
instrução é uma expressão constante porque ambos os operandos do ==
operador são constantes.the boolean expression of the if
statement is a constant expression because both operands of the ==
operator are constants. Como a expressão constante é avaliada em tempo de compilação, produzindo o valor false
, a Console.WriteLine
invocação é considerada inacessível.As the constant expression is evaluated at compile-time, producing the value false
, the Console.WriteLine
invocation is considered unreachable. No entanto, se i
for alterado para ser uma variável localHowever, if i
is changed to be a local variable
void F() {
int i = 1;
if (i == 2) Console.WriteLine("reachable");
}
a Console.WriteLine
invocação é considerada acessível, apesar de, na realidade, nunca será executada.the Console.WriteLine
invocation is considered reachable, even though, in reality, it will never be executed.
O bloco de um membro de função é sempre considerado acessível.The block of a function member is always considered reachable. Ao avaliar sucessivamente as regras de acessibilidade de cada instrução em um bloco, a acessibilidade de qualquer instrução específica pode ser determinada.By successively evaluating the reachability rules of each statement in a block, the reachability of any given statement can be determined.
No exemploIn the example
void F(int x) {
Console.WriteLine("start");
if (x < 0) Console.WriteLine("negative");
}
a acessibilidade do segundo Console.WriteLine
é determinada da seguinte maneira:the reachability of the second Console.WriteLine
is determined as follows:
- A primeira
Console.WriteLine
instrução de expressão pode ser acessada porque o bloco doF
método está acessível.The firstConsole.WriteLine
expression statement is reachable because the block of theF
method is reachable. - O ponto de extremidade da primeira
Console.WriteLine
instrução de expressão pode ser acessado porque essa instrução pode ser acessada.The end point of the firstConsole.WriteLine
expression statement is reachable because that statement is reachable. - A
if
instrução pode ser acessada porque o ponto final da primeiraConsole.WriteLine
instrução de expressão está acessível.Theif
statement is reachable because the end point of the firstConsole.WriteLine
expression statement is reachable. - A segunda
Console.WriteLine
instrução de expressão está acessível porque a expressão booliana daif
instrução não tem o valor constantefalse
.The secondConsole.WriteLine
expression statement is reachable because the boolean expression of theif
statement does not have the constant valuefalse
.
Há duas situações em que é um erro de tempo de compilação para o ponto de extremidade de uma instrução ser acessível:There are two situations in which it is a compile-time error for the end point of a statement to be reachable:
- Como a
switch
instrução não permite que uma seção de comutador "passe" para a próxima seção switch, é um erro de tempo de compilação para o ponto final da lista de instruções de uma seção de switch ser acessível.Because theswitch
statement does not permit a switch section to "fall through" to the next switch section, it is a compile-time error for the end point of the statement list of a switch section to be reachable. Se esse erro ocorrer, normalmente é uma indicação de que umabreak
instrução está ausente.If this error occurs, it is typically an indication that abreak
statement is missing. - É um erro de tempo de compilação para o ponto de extremidade do bloco de um membro de função que computa um valor a ser acessado.It is a compile-time error for the end point of the block of a function member that computes a value to be reachable. Se esse erro ocorrer, normalmente é uma indicação de que uma
return
instrução está ausente.If this error occurs, it typically is an indication that areturn
statement is missing.
BlocosBlocks
Um bloco permite a produção de várias instruções em contextos nos quais uma única instrução é permitida.A block permits multiple statements to be written in contexts where a single statement is allowed.
block
: '{' statement_list? '}'
;
Um bloco consiste em um statement_list opcional (listas de instruções), entre chaves.A block consists of an optional statement_list (Statement lists), enclosed in braces. Se a lista de instruções for omitida, o bloco será considerado vazio.If the statement list is omitted, the block is said to be empty.
Um bloco pode conter instruções de declaração (instruções de declaração).A block may contain declaration statements (Declaration statements). O escopo de uma variável local ou constante declarada em um bloco é o bloco.The scope of a local variable or constant declared in a block is the block.
Um bloco é executado da seguinte maneira:A block is executed as follows:
- Se o bloco estiver vazio, o controle será transferido para o ponto de extremidade do bloco.If the block is empty, control is transferred to the end point of the block.
- Se o bloco não estiver vazio, o controle será transferido para a lista de instruções.If the block is not empty, control is transferred to the statement list. Quando e se o controle atingir o ponto de extremidade da lista de instruções, o controle será transferido para o ponto de extremidade do bloco.When and if control reaches the end point of the statement list, control is transferred to the end point of the block.
A lista de instruções de um bloco pode ser acessada se o próprio bloco estiver acessível.The statement list of a block is reachable if the block itself is reachable.
O ponto de extremidade de um bloco pode ser acessado se o bloco estiver vazio ou se o ponto final da lista de instruções estiver acessível.The end point of a block is reachable if the block is empty or if the end point of the statement list is reachable.
Um bloco que contém uma ou mais yield
instruções (a instrução yield) é chamado de bloco de iterador.A block that contains one or more yield
statements (The yield statement) is called an iterator block. Os blocos de iteradores são usados para implementar membros de função como iteradores (iteradores).Iterator blocks are used to implement function members as iterators (Iterators). Algumas restrições adicionais se aplicam a blocos de iteradores:Some additional restrictions apply to iterator blocks:
- É um erro de tempo de compilação para
return
que uma instrução apareça em um bloco de iterador (mas asyield return
instruções são permitidas).It is a compile-time error for areturn
statement to appear in an iterator block (butyield return
statements are permitted). - É um erro de tempo de compilação para um bloco de iterador conter um contexto não seguro (contextos não seguros).It is a compile-time error for an iterator block to contain an unsafe context (Unsafe contexts). Um bloco do iterador sempre define um contexto seguro, mesmo quando sua declaração está aninhada em um contexto sem segurança.An iterator block always defines a safe context, even when its declaration is nested in an unsafe context.
Listas de instruçõesStatement lists
Uma *lista de instruções _ consiste em uma ou mais instruções escritas em sequência.A *statement list _ consists of one or more statements written in sequence. As listas de instruções ocorrem em _block * s (blocos) e no Switch_block s (a instrução switch).Statement lists occur in _block*s (Blocks) and in switch_block s (The switch statement).
statement_list
: statement+
;
Uma lista de instruções é executada transferindo o controle para a primeira instrução.A statement list is executed by transferring control to the first statement. Quando e se o controle atingir o ponto de extremidade de uma instrução, o controle será transferido para a próxima instrução.When and if control reaches the end point of a statement, control is transferred to the next statement. Quando e se o controle atingir o ponto de extremidade da última instrução, o controle será transferido para o ponto de extremidade da lista de instruções.When and if control reaches the end point of the last statement, control is transferred to the end point of the statement list.
Uma instrução em uma lista de instruções pode ser acessada se pelo menos uma das seguintes opções for verdadeira:A statement in a statement list is reachable if at least one of the following is true:
- A instrução é a primeira instrução e a própria lista de instruções pode ser acessada.The statement is the first statement and the statement list itself is reachable.
- O ponto de extremidade da instrução anterior pode ser acessado.The end point of the preceding statement is reachable.
- A instrução é uma instrução rotulada e o rótulo é referenciado por uma
goto
instrução alcançável.The statement is a labeled statement and the label is referenced by a reachablegoto
statement.
O ponto de extremidade de uma lista de instruções pode ser acessado se o ponto final da última instrução na lista estiver acessível.The end point of a statement list is reachable if the end point of the last statement in the list is reachable.
A instrução vaziaThe empty statement
Um empty_statement não faz nada.An empty_statement does nothing.
empty_statement
: ';'
;
Uma instrução vazia é usada quando não há nenhuma operação a ser executada em um contexto em que uma instrução é necessária.An empty statement is used when there are no operations to perform in a context where a statement is required.
A execução de uma instrução vazia simplesmente transfere o controle para o ponto de extremidade da instrução.Execution of an empty statement simply transfers control to the end point of the statement. Assim, o ponto de extremidade de uma instrução vazia estará acessível se a instrução vazia puder ser acessada.Thus, the end point of an empty statement is reachable if the empty statement is reachable.
Uma instrução vazia pode ser usada ao gravar uma while
instrução com um corpo nulo:An empty statement can be used when writing a while
statement with a null body:
bool ProcessMessage() {...}
void ProcessMessages() {
while (ProcessMessage())
;
}
Além disso, uma instrução vazia pode ser usada para declarar um rótulo logo antes do fechamento " }
" de um bloco:Also, an empty statement can be used to declare a label just before the closing "}
" of a block:
void F() {
...
if (done) goto exit;
...
exit: ;
}
Instruções rotuladasLabeled statements
Uma labeled_statement permite que uma instrução seja prefixada por um rótulo.A labeled_statement permits a statement to be prefixed by a label. Instruções rotuladas são permitidas em blocos, mas não são permitidas como instruções inseridas.Labeled statements are permitted in blocks, but are not permitted as embedded statements.
labeled_statement
: identifier ':' statement
;
Uma instrução rotulada declara um rótulo com o nome fornecido pelo identificador.A labeled statement declares a label with the name given by the identifier. O escopo de um rótulo é o bloco inteiro no qual o rótulo é declarado, incluindo qualquer bloco aninhado.The scope of a label is the whole block in which the label is declared, including any nested blocks. É um erro de tempo de compilação para dois rótulos com o mesmo nome para ter escopos sobrepostos.It is a compile-time error for two labels with the same name to have overlapping scopes.
Um rótulo pode ser referenciado de goto
instruções (a instrução goto) dentro do escopo do rótulo.A label can be referenced from goto
statements (The goto statement) within the scope of the label. Isso significa que as goto
instruções podem transferir o controle dentro de blocos e fora de blocos, mas nunca em blocos.This means that goto
statements can transfer control within blocks and out of blocks, but never into blocks.
Os rótulos têm seu próprio espaço de declaração e não interferem em outros identificadores.Labels have their own declaration space and do not interfere with other identifiers. O exemploThe example
int F(int x) {
if (x >= 0) goto x;
x = -x;
x: return x;
}
é válido e usa o nome x
como um parâmetro e um rótulo.is valid and uses the name x
as both a parameter and a label.
A execução de uma instrução rotulada corresponde exatamente à execução da instrução após o rótulo.Execution of a labeled statement corresponds exactly to execution of the statement following the label.
Além da acessibilidade fornecida pelo fluxo de controle normal, uma instrução rotulada pode ser acessada se o rótulo for referenciado por uma goto
instrução alcançável.In addition to the reachability provided by normal flow of control, a labeled statement is reachable if the label is referenced by a reachable goto
statement. (Exceção: se uma goto
instrução estiver dentro de um try
que inclui um finally
bloco, e a instrução rotulada estiver fora do try
, e o ponto final do finally
bloco estiver inacessível, a instrução rotulada não estará acessível a partir dessa goto
instrução.)(Exception: If a goto
statement is inside a try
that includes a finally
block, and the labeled statement is outside the try
, and the end point of the finally
block is unreachable, then the labeled statement is not reachable from that goto
statement.)
Instruções de declaraçãoDeclaration statements
Um declaration_statement declara uma variável ou constante local.A declaration_statement declares a local variable or constant. Instruções de declaração são permitidas em blocos, mas não são permitidas como instruções inseridas.Declaration statements are permitted in blocks, but are not permitted as embedded statements.
declaration_statement
: local_variable_declaration ';'
| local_constant_declaration ';'
;
Declarações de variáveis locaisLocal variable declarations
Um local_variable_declaration declara uma ou mais variáveis locais.A local_variable_declaration declares one or more local variables.
local_variable_declaration
: local_variable_type local_variable_declarators
;
local_variable_type
: type
| 'var'
;
local_variable_declarators
: local_variable_declarator
| local_variable_declarators ',' local_variable_declarator
;
local_variable_declarator
: identifier
| identifier '=' local_variable_initializer
;
local_variable_initializer
: expression
| array_initializer
| local_variable_initializer_unsafe
;
A local_variable_type de uma local_variable_declaration especifica diretamente o tipo das variáveis introduzidas pela declaração ou indica com o identificador var
que o tipo deve ser inferido com base em um inicializador.The local_variable_type of a local_variable_declaration either directly specifies the type of the variables introduced by the declaration, or indicates with the identifier var
that the type should be inferred based on an initializer. O tipo é seguido por uma lista de local_variable_declarator s, cada um deles apresentando uma nova variável.The type is followed by a list of local_variable_declarator s, each of which introduces a new variable. Uma local_variable_declarator consiste em um identificador que nomeia a variável, opcionalmente seguido por um =
token "" e uma local_variable_initializer que fornece o valor inicial da variável.A local_variable_declarator consists of an identifier that names the variable, optionally followed by an "=
" token and a local_variable_initializer that gives the initial value of the variable.
No contexto de uma declaração de variável local, o identificador var age como uma palavra-chave contextual (palavras-chave). Quando o local_variable_type é especificado como var
e nenhum tipo chamado var
está no escopo, a declaração é uma declaração de variável local digitada implicitamente, cujo tipo é inferido do tipo da expressão do inicializador associado.In the context of a local variable declaration, the identifier var acts as a contextual keyword (Keywords).When the local_variable_type is specified as var
and no type named var
is in scope, the declaration is an implicitly typed local variable declaration, whose type is inferred from the type of the associated initializer expression. As declarações de variáveis locais digitadas implicitamente estão sujeitas às seguintes restrições:Implicitly typed local variable declarations are subject to the following restrictions:
- O local_variable_declaration não pode incluir vários local_variable_declarator s.The local_variable_declaration cannot include multiple local_variable_declarator s.
- O local_variable_declarator deve incluir um local_variable_initializer.The local_variable_declarator must include a local_variable_initializer.
- O local_variable_initializer deve ser uma expressão.The local_variable_initializer must be an expression.
- A expressão do inicializador deve ter um tipo de tempo de compilação.The initializer expression must have a compile-time type.
- A expressão do inicializador não pode se referir à própria variável declaradaThe initializer expression cannot refer to the declared variable itself
Veja a seguir exemplos de declarações de variáveis locais incorretas de tipo implícito:The following are examples of incorrect implicitly typed local variable declarations:
var x; // Error, no initializer to infer type from
var y = {1, 2, 3}; // Error, array initializer not permitted
var z = null; // Error, null does not have a type
var u = x => x + 1; // Error, anonymous functions do not have a type
var v = v++; // Error, initializer cannot refer to variable itself
O valor de uma variável local é obtido em uma expressão usando um Simple_name (nomes simples) e o valor de uma variável local é modificado usando uma atribuição (operadores de atribuição).The value of a local variable is obtained in an expression using a simple_name (Simple names), and the value of a local variable is modified using an assignment (Assignment operators). Uma variável local deve ser definitivamente atribuída (atribuição definitiva) em cada local em que seu valor é obtido.A local variable must be definitely assigned (Definite assignment) at each location where its value is obtained.
O escopo de uma variável local declarada em uma local_variable_declaration é o bloco no qual a declaração ocorre.The scope of a local variable declared in a local_variable_declaration is the block in which the declaration occurs. É um erro fazer referência a uma variável local em uma posição textual que precede a local_variable_declarator da variável local.It is an error to refer to a local variable in a textual position that precedes the local_variable_declarator of the local variable. Dentro do escopo de uma variável local, é um erro de tempo de compilação para declarar outra variável local ou constante com o mesmo nome.Within the scope of a local variable, it is a compile-time error to declare another local variable or constant with the same name.
Uma declaração de variável local que declara várias variáveis é equivalente a várias declarações de variáveis únicas com o mesmo tipo.A local variable declaration that declares multiple variables is equivalent to multiple declarations of single variables with the same type. Além disso, um inicializador de variável em uma declaração de variável local corresponde exatamente a uma instrução de atribuição que é inserida imediatamente após a declaração.Furthermore, a variable initializer in a local variable declaration corresponds exactly to an assignment statement that is inserted immediately after the declaration.
O exemploThe example
void F() {
int x = 1, y, z = x * 2;
}
corresponde exatamente acorresponds exactly to
void F() {
int x; x = 1;
int y;
int z; z = x * 2;
}
Em uma declaração de variável local digitada implicitamente, o tipo da variável local que está sendo declarada é usado como sendo o mesmo que o tipo da expressão usada para inicializar a variável.In an implicitly typed local variable declaration, the type of the local variable being declared is taken to be the same as the type of the expression used to initialize the variable. Por exemplo:For example:
var i = 5;
var s = "Hello";
var d = 1.0;
var numbers = new int[] {1, 2, 3};
var orders = new Dictionary<int,Order>();
As declarações de variável local digitadas implicitamente acima são exatamente equivalentes às seguintes declarações tipadas explicitamente:The implicitly typed local variable declarations above are precisely equivalent to the following explicitly typed declarations:
int i = 5;
string s = "Hello";
double d = 1.0;
int[] numbers = new int[] {1, 2, 3};
Dictionary<int,Order> orders = new Dictionary<int,Order>();
Declarações de constantes locaisLocal constant declarations
Um local_constant_declaration declara uma ou mais constantes locais.A local_constant_declaration declares one or more local constants.
local_constant_declaration
: 'const' type constant_declarators
;
constant_declarators
: constant_declarator (',' constant_declarator)*
;
constant_declarator
: identifier '=' constant_expression
;
O tipo de um local_constant_declaration especifica o tipo das constantes introduzidas pela declaração.The type of a local_constant_declaration specifies the type of the constants introduced by the declaration. O tipo é seguido por uma lista de constant_declarator s, cada um dos quais introduz uma nova constante.The type is followed by a list of constant_declarator s, each of which introduces a new constant. Um constant_declarator consiste em um identificador que nomeia a constante, seguido por um =
token "", seguido por uma constant_expression (expressões constantes) que fornece o valor da constante.A constant_declarator consists of an identifier that names the constant, followed by an "=
" token, followed by a constant_expression (Constant expressions) that gives the value of the constant.
O tipo e constant_expression de uma declaração de constante local devem seguir as mesmas regras que as de uma declaração de membro constante (constantes).The type and constant_expression of a local constant declaration must follow the same rules as those of a constant member declaration (Constants).
O valor de uma constante local é obtido em uma expressão usando um Simple_name (nomes simples).The value of a local constant is obtained in an expression using a simple_name (Simple names).
O escopo de uma constante local é o bloco no qual a declaração ocorre.The scope of a local constant is the block in which the declaration occurs. É um erro fazer referência a uma constante local em uma posição textual que precede sua constant_declarator.It is an error to refer to a local constant in a textual position that precedes its constant_declarator. Dentro do escopo de uma constante local, é um erro de tempo de compilação para declarar outra variável local ou constante com o mesmo nome.Within the scope of a local constant, it is a compile-time error to declare another local variable or constant with the same name.
Uma declaração de constante local que declara várias constantes é equivalente a várias declarações de constantes únicas com o mesmo tipo.A local constant declaration that declares multiple constants is equivalent to multiple declarations of single constants with the same type.
Instruções de expressãoExpression statements
Um expression_statement avalia uma determinada expressão.An expression_statement evaluates a given expression. O valor calculado pela expressão, se houver, é Descartado.The value computed by the expression, if any, is discarded.
expression_statement
: statement_expression ';'
;
statement_expression
: invocation_expression
| null_conditional_invocation_expression
| object_creation_expression
| assignment
| post_increment_expression
| post_decrement_expression
| pre_increment_expression
| pre_decrement_expression
| await_expression
;
Nem todas as expressões são permitidas como instruções.Not all expressions are permitted as statements. Em particular, as expressões como x + y
e x == 1
que meramente computam um valor (que será Descartado) não são permitidas como instruções.In particular, expressions such as x + y
and x == 1
that merely compute a value (which will be discarded), are not permitted as statements.
A execução de um expression_statement avalia a expressão contida e, em seguida, transfere o controle para o ponto de extremidade da expression_statement.Execution of an expression_statement evaluates the contained expression and then transfers control to the end point of the expression_statement. O ponto de extremidade de um expression_statement pode ser acessado se esse expression_statement estiver acessível.The end point of an expression_statement is reachable if that expression_statement is reachable.
Instruções de seleçãoSelection statements
Instruções de seleção selecione um número de possíveis instruções para execução com base no valor de alguma expressão.Selection statements select one of a number of possible statements for execution based on the value of some expression.
selection_statement
: if_statement
| switch_statement
;
Instrução ifThe if statement
A if
instrução seleciona uma instrução para execução com base no valor de uma expressão booliana.The if
statement selects a statement for execution based on the value of a boolean expression.
if_statement
: 'if' '(' boolean_expression ')' embedded_statement
| 'if' '(' boolean_expression ')' embedded_statement 'else' embedded_statement
;
Uma else
parte é associada ao precedentes lexicalmente mais próximo if
que é permitido pela sintaxe.An else
part is associated with the lexically nearest preceding if
that is allowed by the syntax. Portanto, uma if
instrução do formulárioThus, an if
statement of the form
if (x) if (y) F(); else G();
é equivalente ais equivalent to
if (x) {
if (y) {
F();
}
else {
G();
}
}
Uma if
instrução é executada da seguinte maneira:An if
statement is executed as follows:
- O Boolean_expression (expressões booleanas) é avaliado.The boolean_expression (Boolean expressions) is evaluated.
- Se a expressão booliana produz
true
, o controle é transferido para a primeira instrução inserida.If the boolean expression yieldstrue
, control is transferred to the first embedded statement. Quando e se o controle atingir o ponto final dessa instrução, o controle será transferido para o ponto de extremidade daif
instrução.When and if control reaches the end point of that statement, control is transferred to the end point of theif
statement. - Se a expressão booliana produz
false
e se umaelse
parte estiver presente, o controle será transferido para a segunda instrução inserida.If the boolean expression yieldsfalse
and if anelse
part is present, control is transferred to the second embedded statement. Quando e se o controle atingir o ponto final dessa instrução, o controle será transferido para o ponto de extremidade daif
instrução.When and if control reaches the end point of that statement, control is transferred to the end point of theif
statement. - Se a expressão booliana produz
false
e se umaelse
parte não estiver presente, o controle será transferido para o ponto final daif
instrução.If the boolean expression yieldsfalse
and if anelse
part is not present, control is transferred to the end point of theif
statement.
A primeira instrução inserida de uma if
instrução pode ser acessada se a if
instrução estiver acessível e a expressão booliana não tiver o valor constante false
.The first embedded statement of an if
statement is reachable if the if
statement is reachable and the boolean expression does not have the constant value false
.
A segunda instrução inserida de uma if
instrução, se presente, estará acessível se a if
instrução estiver acessível e a expressão booliana não tiver o valor constante true
.The second embedded statement of an if
statement, if present, is reachable if the if
statement is reachable and the boolean expression does not have the constant value true
.
O ponto de extremidade de uma if
instrução pode ser acessado se o ponto de extremidade de pelo menos uma de suas instruções inseridas estiver acessível.The end point of an if
statement is reachable if the end point of at least one of its embedded statements is reachable. Além disso, o ponto de extremidade de uma if
instrução sem nenhuma else
parte será acessível se a if
instrução estiver acessível e a expressão booliana não tiver o valor constante true
.In addition, the end point of an if
statement with no else
part is reachable if the if
statement is reachable and the boolean expression does not have the constant value true
.
A instrução switchThe switch statement
A instrução switch seleciona a execução de uma lista de instruções com um rótulo de comutador associado que corresponde ao valor da expressão switch.The switch statement selects for execution a statement list having an associated switch label that corresponds to the value of the switch expression.
switch_statement
: 'switch' '(' expression ')' switch_block
;
switch_block
: '{' switch_section* '}'
;
switch_section
: switch_label+ statement_list
;
switch_label
: 'case' constant_expression ':'
| 'default' ':'
;
Uma switch_statement consiste na palavra-chave switch
, seguida por uma expressão entre parênteses (chamada de expressão switch), seguida por uma switch_block.A switch_statement consists of the keyword switch
, followed by a parenthesized expression (called the switch expression), followed by a switch_block. O switch_block consiste em zero ou mais switch_section s, entre chaves.The switch_block consists of zero or more switch_section s, enclosed in braces. Cada switch_section consiste em um ou mais switch_label s seguidos por uma statement_list (listas de instruções).Each switch_section consists of one or more switch_label s followed by a statement_list (Statement lists).
O tipo de controle de uma switch
instrução é estabelecido pela expressão switch.The governing type of a switch
statement is established by the switch expression.
- Se o tipo da expressão switch for,,,,,,,,,
sbyte
byte
short
ushort
int
uint
long
ulong
bool
char
,string
ou um enum_type, ou se for o tipo anulável correspondente a um desses tipos, esse será o tipo regulador daswitch
instrução.If the type of the switch expression issbyte
,byte
,short
,ushort
,int
,uint
,long
,ulong
,bool
,char
,string
, or an enum_type, or if it is the nullable type corresponding to one of these types, then that is the governing type of theswitch
statement. - Caso contrário, exatamente uma conversão implícita definida pelo usuário (conversões definidas pelo usuário) deve existir a partir do tipo da expressão switch para um dos seguintes tipos de controle possíveis:,,,,,,,
sbyte
byte
short
ushort
int
uint
long
ulong
,char
,string
ou, um tipo anulável correspondente a um desses tipos.Otherwise, exactly one user-defined implicit conversion (User-defined conversions) must exist from the type of the switch expression to one of the following possible governing types:sbyte
,byte
,short
,ushort
,int
,uint
,long
,ulong
,char
,string
, or, a nullable type corresponding to one of those types. - Caso contrário, se nenhuma conversão implícita existir, ou se houver mais de uma conversão implícita, ocorrerá um erro em tempo de compilação.Otherwise, if no such implicit conversion exists, or if more than one such implicit conversion exists, a compile-time error occurs.
A expressão constante de cada case
rótulo deve indicar um valor que é implicitamente conversível (conversões implícitas) para o tipo regulador da switch
instrução.The constant expression of each case
label must denote a value that is implicitly convertible (Implicit conversions) to the governing type of the switch
statement. Um erro de tempo de compilação ocorre se dois ou mais case
Rótulos na mesma switch
instrução especificarem o mesmo valor de constante.A compile-time error occurs if two or more case
labels in the same switch
statement specify the same constant value.
Pode haver no máximo um default
rótulo em uma instrução switch.There can be at most one default
label in a switch statement.
Uma switch
instrução é executada da seguinte maneira:A switch
statement is executed as follows:
- A expressão switch é avaliada e convertida no tipo regulador.The switch expression is evaluated and converted to the governing type.
- Se uma das constantes especificadas em um
case
rótulo na mesmaswitch
instrução for igual ao valor da expressão switch, o controle será transferido para a lista de instruções após ocase
rótulo correspondente.If one of the constants specified in acase
label in the sameswitch
statement is equal to the value of the switch expression, control is transferred to the statement list following the matchedcase
label. - Se nenhuma das constantes especificadas em
case
Rótulos na mesmaswitch
instrução for igual ao valor da expressão switch e, se umdefault
rótulo estiver presente, o controle será transferido para a lista de instruções após odefault
rótulo.If none of the constants specified incase
labels in the sameswitch
statement is equal to the value of the switch expression, and if adefault
label is present, control is transferred to the statement list following thedefault
label. - Se nenhuma das constantes especificadas em
case
Rótulos na mesmaswitch
instrução for igual ao valor da expressão switch e, se nenhumdefault
rótulo estiver presente, o controle será transferido para o ponto final daswitch
instrução.If none of the constants specified incase
labels in the sameswitch
statement is equal to the value of the switch expression, and if nodefault
label is present, control is transferred to the end point of theswitch
statement.
Se o ponto de extremidade da lista de instruções de uma seção de comutador estiver acessível, ocorrerá um erro em tempo de compilação.If the end point of the statement list of a switch section is reachable, a compile-time error occurs. Isso é conhecido como a regra "não cair".This is known as the "no fall through" rule. O exemploThe example
switch (i) {
case 0:
CaseZero();
break;
case 1:
CaseOne();
break;
default:
CaseOthers();
break;
}
é válido porque nenhuma seção de opção tem um ponto de extremidade acessível.is valid because no switch section has a reachable end point. Ao contrário de C e C++, a execução de uma seção de comutador não é permitida para "passar" para a próxima seção de switch e o exemploUnlike C and C++, execution of a switch section is not permitted to "fall through" to the next switch section, and the example
switch (i) {
case 0:
CaseZero();
case 1:
CaseZeroOrOne();
default:
CaseAny();
}
resulta em um erro de tempo de compilação.results in a compile-time error. Quando a execução de uma seção switch é seguida pela execução de outra seção switch, uma goto case
instrução or explícita goto default
deve ser usada:When execution of a switch section is to be followed by execution of another switch section, an explicit goto case
or goto default
statement must be used:
switch (i) {
case 0:
CaseZero();
goto case 1;
case 1:
CaseZeroOrOne();
goto default;
default:
CaseAny();
break;
}
Vários rótulos são permitidos em um switch_section.Multiple labels are permitted in a switch_section. O exemploThe example
switch (i) {
case 0:
CaseZero();
break;
case 1:
CaseOne();
break;
case 2:
default:
CaseTwo();
break;
}
é válido.is valid. O exemplo não viola a regra "no enquadramento" porque os rótulos case 2:
e default:
fazem parte do mesmo switch_section.The example does not violate the "no fall through" rule because the labels case 2:
and default:
are part of the same switch_section.
A regra "no enquadramento" impede uma classe comum de bugs que ocorrem em C e C++ quando as break
instruções são acidentalmente omitidas.The "no fall through" rule prevents a common class of bugs that occur in C and C++ when break
statements are accidentally omitted. Além disso, devido a essa regra, as seções switch de uma switch
instrução podem ser reorganizadas arbitrariamente sem afetar o comportamento da instrução.In addition, because of this rule, the switch sections of a switch
statement can be arbitrarily rearranged without affecting the behavior of the statement. Por exemplo, as seções da switch
instrução acima podem ser revertidas sem afetar o comportamento da instrução:For example, the sections of the switch
statement above can be reversed without affecting the behavior of the statement:
switch (i) {
default:
CaseAny();
break;
case 1:
CaseZeroOrOne();
goto default;
case 0:
CaseZero();
goto case 1;
}
A lista de instruções de uma seção de alternância normalmente termina em uma break
goto case
instrução, ou goto default
, mas qualquer construção que renderiza o ponto final da lista de instrução inacessível é permitida.The statement list of a switch section typically ends in a break
, goto case
, or goto default
statement, but any construct that renders the end point of the statement list unreachable is permitted. Por exemplo, uma while
instrução controlada pela expressão booliana true
é conhecida como nunca atingir seu ponto de extremidade.For example, a while
statement controlled by the boolean expression true
is known to never reach its end point. Da mesma forma, uma throw
return
instrução or sempre transfere o controle em outro lugar e nunca atinge seu ponto de extremidade.Likewise, a throw
or return
statement always transfers control elsewhere and never reaches its end point. Portanto, o exemplo a seguir é válido:Thus, the following example is valid:
switch (i) {
case 0:
while (true) F();
case 1:
throw new ArgumentException();
case 2:
return;
}
O tipo regulador de uma switch
instrução pode ser o tipo string
.The governing type of a switch
statement may be the type string
. Por exemplo:For example:
void DoCommand(string command) {
switch (command.ToLower()) {
case "run":
DoRun();
break;
case "save":
DoSave();
break;
case "quit":
DoQuit();
break;
default:
InvalidCommand(command);
break;
}
}
Como os operadores de igualdade de cadeia de caracteres (operadores de igualdade de cadeia de caracteres), a instrução diferencia switch
maiúsculas de minúsculas e executará uma determinada seção de comutador somente se a cadeia de caracteres de expressão switch corresponder exatamente a uma case
constanteLike the string equality operators (String equality operators), the switch
statement is case sensitive and will execute a given switch section only if the switch expression string exactly matches a case
label constant.
Quando o tipo regulador de uma switch
instrução é string
, o valor null
é permitido como uma constante de rótulo de caso.When the governing type of a switch
statement is string
, the value null
is permitted as a case label constant.
O statement_list s de um switch_block pode conter instruções de declaração (instruções de declaração).The statement_list s of a switch_block may contain declaration statements (Declaration statements). O escopo de uma variável local ou constante declarada em um bloco switch é o bloco switch.The scope of a local variable or constant declared in a switch block is the switch block.
A lista de instruções de uma determinada seção de comutador pode ser acessada se a switch
instrução estiver acessível e pelo menos uma das seguintes opções for verdadeira:The statement list of a given switch section is reachable if the switch
statement is reachable and at least one of the following is true:
- A expressão switch é um valor não constante.The switch expression is a non-constant value.
- A expressão switch é um valor constante que corresponde a um
case
rótulo na seção switch.The switch expression is a constant value that matches acase
label in the switch section. - A expressão switch é um valor constante que não corresponde a nenhum
case
rótulo e a seção switch contém odefault
rótulo.The switch expression is a constant value that doesn't match anycase
label, and the switch section contains thedefault
label. - Um rótulo de switch da seção switch é referenciado por uma
goto case
instrução ou alcançávelgoto default
.A switch label of the switch section is referenced by a reachablegoto case
orgoto default
statement.
O ponto de extremidade de uma switch
instrução pode ser acessado se pelo menos uma das seguintes opções for verdadeira:The end point of a switch
statement is reachable if at least one of the following is true:
- A
switch
instrução contém umabreak
instrução alcançável que sai daswitch
instrução.Theswitch
statement contains a reachablebreak
statement that exits theswitch
statement. - A
switch
instrução está acessível, a expressão switch é um valor não constante e nenhumdefault
rótulo está presente.Theswitch
statement is reachable, the switch expression is a non-constant value, and nodefault
label is present. - A
switch
instrução está acessível, a expressão switch é um valor constante que não corresponde a nenhumcase
rótulo e nenhumdefault
rótulo está presente.Theswitch
statement is reachable, the switch expression is a constant value that doesn't match anycase
label, and nodefault
label is present.
Instruções de iteraçãoIteration statements
Instruções de iteração executa repetidamente uma instrução inserida.Iteration statements repeatedly execute an embedded statement.
iteration_statement
: while_statement
| do_statement
| for_statement
| foreach_statement
;
A instrução whileThe while statement
A while
instrução Executa condicionalmente uma instrução inserida zero ou mais vezes.The while
statement conditionally executes an embedded statement zero or more times.
while_statement
: 'while' '(' boolean_expression ')' embedded_statement
;
Uma while
instrução é executada da seguinte maneira:A while
statement is executed as follows:
- O Boolean_expression (expressões booleanas) é avaliado.The boolean_expression (Boolean expressions) is evaluated.
- Se a expressão booliana produz
true
, o controle é transferido para a instrução inserida.If the boolean expression yieldstrue
, control is transferred to the embedded statement. Quando e se o controle atingir o ponto de extremidade da instrução inserida (possivelmente da execução de umacontinue
instrução), o controle será transferido para o início dawhile
instrução.When and if control reaches the end point of the embedded statement (possibly from execution of acontinue
statement), control is transferred to the beginning of thewhile
statement. - Se a expressão booliana produz
false
, o controle é transferido para o ponto final dawhile
instrução.If the boolean expression yieldsfalse
, control is transferred to the end point of thewhile
statement.
Dentro da instrução inserida de uma while
instrução, uma break
instrução (a instrução break) pode ser usada para transferir o controle para o ponto final da while
instrução (encerrando, assim, a iteração da instrução incorporada) e uma continue
instrução (a instrução Continue) pode ser usada para transferir o controle para o ponto final da instrução inserida (assim, executando outra iteração da while
instrução).Within the embedded statement of a while
statement, a break
statement (The break statement) may be used to transfer control to the end point of the while
statement (thus ending iteration of the embedded statement), and a continue
statement (The continue statement) may be used to transfer control to the end point of the embedded statement (thus performing another iteration of the while
statement).
A instrução inserida de uma while
instrução pode ser acessada se a while
instrução estiver acessível e a expressão booliana não tiver o valor constante false
.The embedded statement of a while
statement is reachable if the while
statement is reachable and the boolean expression does not have the constant value false
.
O ponto de extremidade de uma while
instrução pode ser acessado se pelo menos uma das seguintes opções for verdadeira:The end point of a while
statement is reachable if at least one of the following is true:
- A
while
instrução contém umabreak
instrução alcançável que sai dawhile
instrução.Thewhile
statement contains a reachablebreak
statement that exits thewhile
statement. - A
while
instrução está acessível e a expressão booliana não tem o valor constantetrue
.Thewhile
statement is reachable and the boolean expression does not have the constant valuetrue
.
A instrução doThe do statement
A do
instrução Executa condicionalmente uma instrução inserida uma ou mais vezes.The do
statement conditionally executes an embedded statement one or more times.
do_statement
: 'do' embedded_statement 'while' '(' boolean_expression ')' ';'
;
Uma do
instrução é executada da seguinte maneira:A do
statement is executed as follows:
- O controle é transferido para a instrução inserida.Control is transferred to the embedded statement.
- Quando e se o controle atingir o ponto de extremidade da instrução inserida (possivelmente da execução de uma
continue
instrução), a Boolean_expression (expressões booleanas) será avaliada.When and if control reaches the end point of the embedded statement (possibly from execution of acontinue
statement), the boolean_expression (Boolean expressions) is evaluated. Se a expressão booliana produztrue
, o controle é transferido para o início dado
instrução.If the boolean expression yieldstrue
, control is transferred to the beginning of thedo
statement. Caso contrário, o controle será transferido para o ponto de extremidade dado
instrução.Otherwise, control is transferred to the end point of thedo
statement.
Dentro da instrução inserida de uma do
instrução, uma break
instrução (a instrução break) pode ser usada para transferir o controle para o ponto final da do
instrução (encerrando assim a iteração da instrução inserida) e uma continue
instrução (a instrução Continue) pode ser usada para transferir o controle para o ponto final da instrução inserida.Within the embedded statement of a do
statement, a break
statement (The break statement) may be used to transfer control to the end point of the do
statement (thus ending iteration of the embedded statement), and a continue
statement (The continue statement) may be used to transfer control to the end point of the embedded statement.
A instrução inserida de uma do
instrução pode ser acessada se a do
instrução estiver acessível.The embedded statement of a do
statement is reachable if the do
statement is reachable.
O ponto de extremidade de uma do
instrução pode ser acessado se pelo menos uma das seguintes opções for verdadeira:The end point of a do
statement is reachable if at least one of the following is true:
- A
do
instrução contém umabreak
instrução alcançável que sai dado
instrução.Thedo
statement contains a reachablebreak
statement that exits thedo
statement. - O ponto de extremidade da instrução inserida pode ser acessado e a expressão booliana não tem o valor constante
true
.The end point of the embedded statement is reachable and the boolean expression does not have the constant valuetrue
.
A instrução forThe for statement
A for
instrução avalia uma sequência de expressões de inicialização e, em seguida, enquanto uma condição é verdadeira, executa repetidamente uma instrução inserida e avalia uma sequência de expressões de iteração.The for
statement evaluates a sequence of initialization expressions and then, while a condition is true, repeatedly executes an embedded statement and evaluates a sequence of iteration expressions.
for_statement
: 'for' '(' for_initializer? ';' for_condition? ';' for_iterator? ')' embedded_statement
;
for_initializer
: local_variable_declaration
| statement_expression_list
;
for_condition
: boolean_expression
;
for_iterator
: statement_expression_list
;
statement_expression_list
: statement_expression (',' statement_expression)*
;
O for_initializer, se presente, consiste em uma local_variable_declaration (declarações de variável local) ou uma lista de statement_expression s (instruções de expressão) separadas por vírgulas.The for_initializer, if present, consists of either a local_variable_declaration (Local variable declarations) or a list of statement_expression s (Expression statements) separated by commas. O escopo de uma variável local declarada por um for_initializer começa na local_variable_declarator da variável e se estende ao final da instrução inserida.The scope of a local variable declared by a for_initializer starts at the local_variable_declarator for the variable and extends to the end of the embedded statement. O escopo inclui o for_condition e o for_iterator.The scope includes the for_condition and the for_iterator.
A for_condition, se presente, deve ser uma Boolean_expression (expressões booleanas).The for_condition, if present, must be a boolean_expression (Boolean expressions).
A for_iterator, se presente, consiste em uma lista de statement_expression s (instruções de expressão) separadas por vírgulas.The for_iterator, if present, consists of a list of statement_expression s (Expression statements) separated by commas.
Uma instrução for é executada da seguinte maneira:A for statement is executed as follows:
- Se uma for_initializer estiver presente, os inicializadores de variável ou as expressões de instrução serão executadas na ordem em que são gravadas.If a for_initializer is present, the variable initializers or statement expressions are executed in the order they are written. Esta etapa é executada apenas uma vez.This step is only performed once.
- Se uma for_condition estiver presente, ela será avaliada.If a for_condition is present, it is evaluated.
- Se o for_condition não estiver presente ou se a avaliação resultar
true
, o controle será transferido para a instrução inserida.If the for_condition is not present or if the evaluation yieldstrue
, control is transferred to the embedded statement. Quando e se o controle atingir o ponto de extremidade da instrução inserida (possivelmente da execução de umacontinue
instrução), as expressões do for_iterator, se houver, serão avaliadas em sequência e outra iteração será executada, começando com a avaliação do for_condition na etapa anterior.When and if control reaches the end point of the embedded statement (possibly from execution of acontinue
statement), the expressions of the for_iterator, if any, are evaluated in sequence, and then another iteration is performed, starting with evaluation of the for_condition in the step above. - Se o for_condition estiver presente e a avaliação resultar
false
, o controle será transferido para o ponto de extremidade dafor
instrução.If the for_condition is present and the evaluation yieldsfalse
, control is transferred to the end point of thefor
statement.
Dentro da instrução inserida de uma for
instrução, uma break
instrução (a instrução break) pode ser usada para transferir o controle para o ponto final da for
instrução (encerrando assim a iteração da instrução inserida) e uma continue
instrução (a instrução Continue) pode ser usada para transferir o controle para o ponto de extremidade da instrução inserida (executando o for_iterator e executando outra iteração da for
instrução, começando com o for_condition).Within the embedded statement of a for
statement, a break
statement (The break statement) may be used to transfer control to the end point of the for
statement (thus ending iteration of the embedded statement), and a continue
statement (The continue statement) may be used to transfer control to the end point of the embedded statement (thus executing the for_iterator and performing another iteration of the for
statement, starting with the for_condition).
A instrução inserida de uma for
instrução pode ser acessada se uma das seguintes opções for verdadeira:The embedded statement of a for
statement is reachable if one of the following is true:
- A
for
instrução está acessível e nenhuma for_condition está presente.Thefor
statement is reachable and no for_condition is present. - A
for
instrução está acessível e um for_condition está presente e não tem o valor constantefalse
.Thefor
statement is reachable and a for_condition is present and does not have the constant valuefalse
.
O ponto de extremidade de uma for
instrução pode ser acessado se pelo menos uma das seguintes opções for verdadeira:The end point of a for
statement is reachable if at least one of the following is true:
- A
for
instrução contém umabreak
instrução alcançável que sai dafor
instrução.Thefor
statement contains a reachablebreak
statement that exits thefor
statement. - A
for
instrução está acessível e um for_condition está presente e não tem o valor constantetrue
.Thefor
statement is reachable and a for_condition is present and does not have the constant valuetrue
.
A instrução foreachThe foreach statement
A foreach
instrução enumera os elementos de uma coleção, executando uma instrução incorporada para cada elemento da coleção.The foreach
statement enumerates the elements of a collection, executing an embedded statement for each element of the collection.
foreach_statement
: 'foreach' '(' local_variable_type identifier 'in' expression ')' embedded_statement
;
O tipo e o identificador de uma foreach
instrução declaram a variável * de iteração _ da instrução.The type and identifier of a foreach
statement declare the *iteration variable _ of the statement. Se o var
identificador for fornecido como o _local_variable_type * e nenhum tipo chamado var
estiver no escopo, a variável de iteração será considerada uma variável de iteração digitada implicitamente e seu tipo será usado como sendo o tipo de elemento da foreach
instrução, conforme especificado abaixo.If the var
identifier is given as the _local_variable_type*, and no type named var
is in scope, the iteration variable is said to be an implicitly typed iteration variable, and its type is taken to be the element type of the foreach
statement, as specified below. A variável de iteração corresponde a uma variável local somente leitura com um escopo que se estende pela instrução incorporada.The iteration variable corresponds to a read-only local variable with a scope that extends over the embedded statement. Durante a execução de uma foreach
instrução, a variável de iteração representa o elemento de coleção para o qual uma iteração está sendo executada no momento.During execution of a foreach
statement, the iteration variable represents the collection element for which an iteration is currently being performed. Ocorrerá um erro de tempo de compilação se a instrução inserida tentar modificar a variável de iteração (por meio de atribuição ou os ++
--
operadores e) ou passar a variável de iteração como um ref
out
parâmetro ou.A compile-time error occurs if the embedded statement attempts to modify the iteration variable (via assignment or the ++
and --
operators) or pass the iteration variable as a ref
or out
parameter.
A seguir, para fins de brevidade,, IEnumerable
IEnumerator
IEnumerable<T>
e IEnumerator<T>
consulte os tipos correspondentes nos namespaces System.Collections
e System.Collections.Generic
.In the following, for brevity, IEnumerable
, IEnumerator
, IEnumerable<T>
and IEnumerator<T>
refer to the corresponding types in the namespaces System.Collections
and System.Collections.Generic
.
O processamento em tempo de compilação de uma instrução foreach determina primeiro o tipo de coleção _, tipo de _enumerador_ e _ tipo de elemento da expressão.The compile-time processing of a foreach statement first determines the collection type _, _enumerator type_ and _ element type of the expression. Essa determinação continua da seguinte maneira:This determination proceeds as follows:
Se o tipo
X
de expressão for um tipo de matriz, haverá uma conversão de referência implícita deX
para aIEnumerable
interface (desde queSystem.Array
implementa essa interface).If the typeX
of expression is an array type then there is an implicit reference conversion fromX
to theIEnumerable
interface (sinceSystem.Array
implements this interface). O tipo de coleção _ é aIEnumerable
interface, o _tipo de enumerador_ é aIEnumerator
interface e o tipo _ elemento é o tipo de elemento do tipo de matrizX
.The collection type _ is theIEnumerable
interface, the _enumerator type_ is theIEnumerator
interface and the _ element type is the element type of the array typeX
.Se o tipo
X
de expressão fordynamic
, haverá uma conversão implícita de expression para aIEnumerable
interface (conversões dinâmicas implícitas).If the typeX
of expression isdynamic
then there is an implicit conversion from expression to theIEnumerable
interface (Implicit dynamic conversions). O tipo de coleção _ é aIEnumerable
interface e o _tipo de enumerador*_ é aIEnumerator
interface.The collection type _ is theIEnumerable
interface and the _enumerator type*_ is theIEnumerator
interface. Se ovar
identificador for fornecido como o _local_variable_type *, o tipo de elemento serádynamic
, caso contrário, seráobject
.If thevar
identifier is given as the _local_variable_type* then the element type isdynamic
, otherwise it isobject
.Caso contrário, determine se o tipo
X
tem umGetEnumerator
método apropriado:Otherwise, determine whether the typeX
has an appropriateGetEnumerator
method:- Executar pesquisa de membro no tipo
X
com identificadorGetEnumerator
e nenhum argumento de tipo.Perform member lookup on the typeX
with identifierGetEnumerator
and no type arguments. Se a pesquisa de membro não produzir uma correspondência ou se gerar uma ambiguidade ou produzir uma correspondência que não seja um grupo de métodos, verifique se há uma interface enumerável, conforme descrito abaixo.If the member lookup does not produce a match, or it produces an ambiguity, or produces a match that is not a method group, check for an enumerable interface as described below. É recomendável que um aviso seja emitido se a pesquisa de membros produzir qualquer coisa, exceto um grupo de métodos ou nenhuma correspondência.It is recommended that a warning be issued if member lookup produces anything except a method group or no match. - Execute a resolução de sobrecarga usando o grupo de métodos resultante e uma lista de argumentos vazia.Perform overload resolution using the resulting method group and an empty argument list. Se a resolução de sobrecarga não resultar em métodos aplicáveis, resultar em uma ambiguidade ou resultar em um único método melhor, mas o método for estático ou não público, verifique se há uma interface enumerável, conforme descrito abaixo.If overload resolution results in no applicable methods, results in an ambiguity, or results in a single best method but that method is either static or not public, check for an enumerable interface as described below. É recomendável que um aviso seja emitido se a resolução de sobrecarga produzir algo, exceto um método de instância pública não ambígua, ou nenhum dos métodos aplicáveis.It is recommended that a warning be issued if overload resolution produces anything except an unambiguous public instance method or no applicable methods.
- Se o tipo
E
de retorno doGetEnumerator
método não for uma classe, struct ou tipo de interface, um erro será produzido e nenhuma etapa adicional será executada.If the return typeE
of theGetEnumerator
method is not a class, struct or interface type, an error is produced and no further steps are taken. - A pesquisa de membros é executada em
E
com o identificadorCurrent
e nenhum argumento de tipo.Member lookup is performed onE
with the identifierCurrent
and no type arguments. Se a pesquisa de membro não produzir nenhuma correspondência, o resultado é um erro ou o resultado é qualquer coisa, exceto uma propriedade de instância pública que permite a leitura, um erro é produzido e nenhuma etapa adicional é executada.If the member lookup produces no match, the result is an error, or the result is anything except a public instance property that permits reading, an error is produced and no further steps are taken. - A pesquisa de membros é executada em
E
com o identificadorMoveNext
e nenhum argumento de tipo.Member lookup is performed onE
with the identifierMoveNext
and no type arguments. Se a pesquisa de membro não produzir nenhuma correspondência, o resultado é um erro ou o resultado é qualquer coisa, exceto um grupo de métodos, um erro é produzido e nenhuma etapa adicional é executada.If the member lookup produces no match, the result is an error, or the result is anything except a method group, an error is produced and no further steps are taken. - A resolução de sobrecarga é executada no grupo de métodos com uma lista de argumentos vazia.Overload resolution is performed on the method group with an empty argument list. Se a resolução de sobrecarga não resultar em métodos aplicáveis, resultar em uma ambiguidade ou resultar em um único método melhor, mas esse método for estático ou não público, ou seu tipo de retorno não for
bool
, um erro será produzido e nenhuma etapa adicional será executada.If overload resolution results in no applicable methods, results in an ambiguity, or results in a single best method but that method is either static or not public, or its return type is notbool
, an error is produced and no further steps are taken. - O tipo de coleção _ é
X
, o _tipo de enumerador_ éE
e o tipo _ Element é o tipo daCurrent
propriedade.The collection type _ isX
, the _enumerator type_ isE
, and the _ element type is the type of theCurrent
property.
- Executar pesquisa de membro no tipo
Caso contrário, verifique se há uma interface enumerável:Otherwise, check for an enumerable interface:
- Se entre todos os tipos
Ti
para os quais há uma conversão implícita deX
paraIEnumerable<Ti>
, há um tipo exclusivo deT
queT
não édynamic
e para todos os outrosTi
há uma conversão implícita deIEnumerable<T>
paraIEnumerable<Ti>
, então o * tipo de coleção _ é a interfaceIEnumerable<T>
, o tipo de enumerador é a interfaceIEnumerator<T>
e o _ tipo de elemento* éT
.If among all the typesTi
for which there is an implicit conversion fromX
toIEnumerable<Ti>
, there is a unique typeT
such thatT
is notdynamic
and for all the otherTi
there is an implicit conversion fromIEnumerable<T>
toIEnumerable<Ti>
, then the collection type _ is the interfaceIEnumerable<T>
, the _enumerator type_ is the interfaceIEnumerator<T>
, and the _ element type isT
. - Caso contrário, se houver mais de um desses tipos
T
, um erro será produzido e nenhuma etapa adicional será executada.Otherwise, if there is more than one such typeT
, then an error is produced and no further steps are taken. - Caso contrário, se houver uma conversão implícita de na
X
System.Collections.IEnumerable
interface, o * tipo de coleção _ é essa interface, o tipo de enumerador será a interfaceSystem.Collections.IEnumerator
e o tipo de elemento _ * seráobject
.Otherwise, if there is an implicit conversion fromX
to theSystem.Collections.IEnumerable
interface, then the collection type _ is this interface, the _enumerator type_ is the interfaceSystem.Collections.IEnumerator
, and the _ element type isobject
. - Caso contrário, um erro é produzido e nenhuma etapa adicional é executada.Otherwise, an error is produced and no further steps are taken.
- Se entre todos os tipos
As etapas acima, se forem bem-sucedidas, produzirão um tipo de coleção C
, tipo de enumerador e tipo de elemento de forma inequívoca E
T
.The above steps, if successful, unambiguously produce a collection type C
, enumerator type E
and element type T
. Uma instrução foreach do formulárioA foreach statement of the form
foreach (V v in x) embedded_statement
é então expandido para:is then expanded to:
{
E e = ((C)(x)).GetEnumerator();
try {
while (e.MoveNext()) {
V v = (V)(T)e.Current;
embedded_statement
}
}
finally {
... // Dispose e
}
}
A variável e
não é visível ou acessível à expressão ou à x
instrução incorporada ou a qualquer outro código-fonte do programa.The variable e
is not visible to or accessible to the expression x
or the embedded statement or any other source code of the program. A variável v
é somente leitura na instrução incorporada.The variable v
is read-only in the embedded statement. Se não houver uma conversão explícita (conversões explícitas) de T
(o tipo de elemento) para V
(o local_variable_type na instrução foreach), um erro será produzido e nenhuma outra etapa será executada.If there is not an explicit conversion (Explicit conversions) from T
(the element type) to V
(the local_variable_type in the foreach statement), an error is produced and no further steps are taken. Se x
tiver o valor null
, um System.NullReferenceException
será lançado em tempo de execução.If x
has the value null
, a System.NullReferenceException
is thrown at run-time.
Uma implementação tem permissão para implementar uma determinada instrução foreach de forma diferente, por exemplo, por motivos de desempenho, desde que o comportamento seja consistente com a expansão acima.An implementation is permitted to implement a given foreach-statement differently, e.g. for performance reasons, as long as the behavior is consistent with the above expansion.
O posicionamento de v
dentro do loop while é importante para a forma como ele é capturado por qualquer função anônima que ocorra na embedded_statement.The placement of v
inside the while loop is important for how it is captured by any anonymous function occurring in the embedded_statement.
Por exemplo:For example:
int[] values = { 7, 9, 13 };
Action f = null;
foreach (var value in values)
{
if (f == null) f = () => Console.WriteLine("First value: " + value);
}
f();
Se v
foi declarado fora do loop while, ele seria compartilhado entre todas as iterações e seu valor após o loop for seria o valor final, 13
, que é o que a invocação f
imprimiria.If v
was declared outside of the while loop, it would be shared among all iterations, and its value after the for loop would be the final value, 13
, which is what the invocation of f
would print. Em vez disso, como cada iteração tem sua própria variável v
, aquela capturada pela f
primeira iteração continuará a manter o valor 7
, que é o que será impresso.Instead, because each iteration has its own variable v
, the one captured by f
in the first iteration will continue to hold the value 7
, which is what will be printed. (Observação: versões anteriores do C# declaradas v
fora do loop While.)(Note: earlier versions of C# declared v
outside of the while loop.)
O corpo do bloco finally é construído de acordo com as seguintes etapas:The body of the finally block is constructed according to the following steps:
Se houver uma conversão implícita do na
E
System.IDisposable
interface, entãoIf there is an implicit conversion fromE
to theSystem.IDisposable
interface, thenSe
E
for um tipo de valor não anulável, a cláusula finally será expandida para o equivalente semântico de:IfE
is a non-nullable value type then the finally clause is expanded to the semantic equivalent of:finally { ((System.IDisposable)e).Dispose(); }
Caso contrário, a cláusula finally será expandida para o equivalente semântico de:Otherwise the finally clause is expanded to the semantic equivalent of:
finally { if (e != null) ((System.IDisposable)e).Dispose(); }
Exceto que se
E
for um tipo de valor ou um parâmetro de tipo instanciado para um tipo de valor, a conversão dee
paraSystem.IDisposable
não fará com que a Boxing ocorra.except that ifE
is a value type, or a type parameter instantiated to a value type, then the cast ofe
toSystem.IDisposable
will not cause boxing to occur.Caso contrário, se
E
for um tipo lacrado, a cláusula finally será expandida para um bloco vazio:Otherwise, ifE
is a sealed type, the finally clause is expanded to an empty block:finally { }
Caso contrário, a cláusula finally será expandida para:Otherwise, the finally clause is expanded to:
finally { System.IDisposable d = e as System.IDisposable; if (d != null) d.Dispose(); }
A variável local
d
não é visível ou acessível a nenhum código de usuário.The local variabled
is not visible to or accessible to any user code. Em particular, ele não entra em conflito com nenhuma outra variável cujo escopo inclui o bloco finally.In particular, it does not conflict with any other variable whose scope includes the finally block.
A ordem na qual foreach
percorre os elementos de uma matriz é a seguinte: para os elementos de matrizes unidimensionais são atravessados em ordem de índice crescente, começando com index 0
e terminando com index Length - 1
.The order in which foreach
traverses the elements of an array, is as follows: For single-dimensional arrays elements are traversed in increasing index order, starting with index 0
and ending with index Length - 1
. Para matrizes multidimensionais, os elementos são percorridos de forma que os índices da dimensão mais à direita sejam aumentados primeiro, depois a dimensão à esquerda e assim por diante à esquerda.For multi-dimensional arrays, elements are traversed such that the indices of the rightmost dimension are increased first, then the next left dimension, and so on to the left.
O exemplo a seguir imprime cada valor em uma matriz bidimensional, na ordem do elemento:The following example prints out each value in a two-dimensional array, in element order:
using System;
class Test
{
static void Main() {
double[,] values = {
{1.2, 2.3, 3.4, 4.5},
{5.6, 6.7, 7.8, 8.9}
};
foreach (double elementValue in values)
Console.Write("{0} ", elementValue);
Console.WriteLine();
}
}
A saída produzida é a seguinte:The output produced is as follows:
1.2 2.3 3.4 4.5 5.6 6.7 7.8 8.9
No exemploIn the example
int[] numbers = { 1, 3, 5, 7, 9 };
foreach (var n in numbers) Console.WriteLine(n);
o tipo de n
é inferido como int
, o tipo de elemento de numbers
.the type of n
is inferred to be int
, the element type of numbers
.
Instruções de atalhoJump statements
As instruções de salto transferem o controle incondicionalmente.Jump statements unconditionally transfer control.
jump_statement
: break_statement
| continue_statement
| goto_statement
| return_statement
| throw_statement
;
O local para o qual uma instrução de salto transfere o controle é chamado de destino da instrução de salto.The location to which a jump statement transfers control is called the target of the jump statement.
Quando uma instrução de salto ocorre dentro de um bloco e o destino dessa instrução de salto está fora desse bloco, a instrução de salto é chamada para sair do bloco.When a jump statement occurs within a block, and the target of that jump statement is outside that block, the jump statement is said to exit the block. Embora uma instrução de salto possa transferir o controle para fora de um bloco, ela nunca pode transferir o controle para um bloco.While a jump statement may transfer control out of a block, it can never transfer control into a block.
A execução de instruções de salto é complicada pela presença de instruções intermediárias try
.Execution of jump statements is complicated by the presence of intervening try
statements. Na ausência de tais try
instruções, uma instrução de salto transfere incondicionalmente o controle da instrução de salto para seu destino.In the absence of such try
statements, a jump statement unconditionally transfers control from the jump statement to its target. Na presença dessas instruções intermediárias try
, a execução é mais complexa.In the presence of such intervening try
statements, execution is more complex. Se a instrução de salto sair de um ou mais try
blocos com finally
blocos associados, o controle será transferido inicialmente para o finally
bloco da try
instrução mais interna.If the jump statement exits one or more try
blocks with associated finally
blocks, control is initially transferred to the finally
block of the innermost try
statement. Quando e se o controle atingir o ponto de extremidade de um finally
bloco, o controle será transferido para o finally
bloco da próxima instrução de circunscrição try
.When and if control reaches the end point of a finally
block, control is transferred to the finally
block of the next enclosing try
statement. Esse processo é repetido até que os finally
blocos de todas as instruções intermediárias try
tenham sido executados.This process is repeated until the finally
blocks of all intervening try
statements have been executed.
No exemploIn the example
using System;
class Test
{
static void Main() {
while (true) {
try {
try {
Console.WriteLine("Before break");
break;
}
finally {
Console.WriteLine("Innermost finally block");
}
}
finally {
Console.WriteLine("Outermost finally block");
}
}
Console.WriteLine("After break");
}
}
os finally
blocos associados a duas try
instruções são executados antes de o controle ser transferido para o destino da instrução de salto.the finally
blocks associated with two try
statements are executed before control is transferred to the target of the jump statement.
A saída produzida é a seguinte:The output produced is as follows:
Before break
Innermost finally block
Outermost finally block
After break
A instrução breakThe break statement
A break
instrução sai da instrução,,, ou delimitadora mais próxima switch
while
do
for
foreach
.The break
statement exits the nearest enclosing switch
, while
, do
, for
, or foreach
statement.
break_statement
: 'break' ';'
;
O destino de uma break
instrução é o ponto final da switch
instrução,, while
do
, for
ou delimitadora mais próxima foreach
.The target of a break
statement is the end point of the nearest enclosing switch
, while
, do
, for
, or foreach
statement. Se uma break
instrução não estiver entre uma switch
instrução, while
, do
, for
ou foreach
, ocorrerá um erro de tempo de compilação.If a break
statement is not enclosed by a switch
, while
, do
, for
, or foreach
statement, a compile-time error occurs.
Quando várias switch
while
instruções,, do
, for
ou foreach
são aninhadas umas nas outras, uma break
instrução aplica-se somente à instrução mais interna.When multiple switch
, while
, do
, for
, or foreach
statements are nested within each other, a break
statement applies only to the innermost statement. Para transferir o controle entre vários níveis de aninhamento, uma goto
instrução (instrução goto) deve ser usada.To transfer control across multiple nesting levels, a goto
statement (The goto statement) must be used.
Uma break
instrução não pode sair de um finally
bloco (a instrução try).A break
statement cannot exit a finally
block (The try statement). Quando uma break
instrução ocorre dentro de um finally
bloco, o destino da break
instrução deve estar dentro do mesmo finally
bloco; caso contrário, ocorrerá um erro em tempo de compilação.When a break
statement occurs within a finally
block, the target of the break
statement must be within the same finally
block; otherwise, a compile-time error occurs.
Uma break
instrução é executada da seguinte maneira:A break
statement is executed as follows:
- Se a
break
instrução sair de um ou maistry
blocos comfinally
blocos associados, o controle será transferido inicialmente para ofinally
bloco da instrução mais internatry
.If thebreak
statement exits one or moretry
blocks with associatedfinally
blocks, control is initially transferred to thefinally
block of the innermosttry
statement. Quando e se o controle atingir o ponto de extremidade de umfinally
bloco, o controle será transferido para ofinally
bloco da próxima instrução de circunscriçãotry
.When and if control reaches the end point of afinally
block, control is transferred to thefinally
block of the next enclosingtry
statement. Esse processo é repetido até que osfinally
blocos de todas as instruções intermediáriastry
tenham sido executados.This process is repeated until thefinally
blocks of all interveningtry
statements have been executed. - O controle é transferido para o destino da
break
instrução.Control is transferred to the target of thebreak
statement.
Como uma break
instrução transfere incondicionalmente o controle em outro lugar, o ponto de extremidade de uma break
instrução nunca é acessível.Because a break
statement unconditionally transfers control elsewhere, the end point of a break
statement is never reachable.
A instrução ContinueThe continue statement
A continue
instrução inicia uma nova iteração da instrução,, ou delimitadora mais próxima while
do
for
foreach
.The continue
statement starts a new iteration of the nearest enclosing while
, do
, for
, or foreach
statement.
continue_statement
: 'continue' ';'
;
O destino de uma continue
instrução é o ponto final da instrução inserida da while
do
instrução,, ou delimitadora mais próxima for
foreach
.The target of a continue
statement is the end point of the embedded statement of the nearest enclosing while
, do
, for
, or foreach
statement. Se uma continue
instrução não estiver delimitada por while
uma do
instrução,, for
ou foreach
, ocorrerá um erro em tempo de compilação.If a continue
statement is not enclosed by a while
, do
, for
, or foreach
statement, a compile-time error occurs.
Quando várias while
do
instruções,, for
ou foreach
são aninhadas umas nas outras, uma continue
instrução aplica-se somente à instrução mais interna.When multiple while
, do
, for
, or foreach
statements are nested within each other, a continue
statement applies only to the innermost statement. Para transferir o controle entre vários níveis de aninhamento, uma goto
instrução (instrução goto) deve ser usada.To transfer control across multiple nesting levels, a goto
statement (The goto statement) must be used.
Uma continue
instrução não pode sair de um finally
bloco (a instrução try).A continue
statement cannot exit a finally
block (The try statement). Quando uma continue
instrução ocorre dentro de um finally
bloco, o destino da continue
instrução deve estar dentro do mesmo finally
bloco; caso contrário, ocorrerá um erro em tempo de compilação.When a continue
statement occurs within a finally
block, the target of the continue
statement must be within the same finally
block; otherwise a compile-time error occurs.
Uma continue
instrução é executada da seguinte maneira:A continue
statement is executed as follows:
- Se a
continue
instrução sair de um ou maistry
blocos comfinally
blocos associados, o controle será transferido inicialmente para ofinally
bloco da instrução mais internatry
.If thecontinue
statement exits one or moretry
blocks with associatedfinally
blocks, control is initially transferred to thefinally
block of the innermosttry
statement. Quando e se o controle atingir o ponto de extremidade de umfinally
bloco, o controle será transferido para ofinally
bloco da próxima instrução de circunscriçãotry
.When and if control reaches the end point of afinally
block, control is transferred to thefinally
block of the next enclosingtry
statement. Esse processo é repetido até que osfinally
blocos de todas as instruções intermediáriastry
tenham sido executados.This process is repeated until thefinally
blocks of all interveningtry
statements have been executed. - O controle é transferido para o destino da
continue
instrução.Control is transferred to the target of thecontinue
statement.
Como uma continue
instrução transfere incondicionalmente o controle em outro lugar, o ponto de extremidade de uma continue
instrução nunca é acessível.Because a continue
statement unconditionally transfers control elsewhere, the end point of a continue
statement is never reachable.
A instrução gotoThe goto statement
A goto
instrução transfere o controle para uma instrução que é marcada por um rótulo.The goto
statement transfers control to a statement that is marked by a label.
goto_statement
: 'goto' identifier ';'
| 'goto' 'case' constant_expression ';'
| 'goto' 'default' ';'
;
O destino de uma goto
instrução de identificador é a instrução rotulada com o rótulo fornecido.The target of a goto
identifier statement is the labeled statement with the given label. Se um rótulo com o nome fornecido não existir no membro da função atual ou se a goto
instrução não estiver dentro do escopo do rótulo, ocorrerá um erro em tempo de compilação.If a label with the given name does not exist in the current function member, or if the goto
statement is not within the scope of the label, a compile-time error occurs. Essa regra permite o uso de uma goto
instrução para transferir o controle de um escopo aninhado, mas não para um escopo aninhado.This rule permits the use of a goto
statement to transfer control out of a nested scope, but not into a nested scope. No exemploIn the example
using System;
class Test
{
static void Main(string[] args) {
string[,] table = {
{"Red", "Blue", "Green"},
{"Monday", "Wednesday", "Friday"}
};
foreach (string str in args) {
int row, colm;
for (row = 0; row <= 1; ++row)
for (colm = 0; colm <= 2; ++colm)
if (str == table[row,colm])
goto done;
Console.WriteLine("{0} not found", str);
continue;
done:
Console.WriteLine("Found {0} at [{1}][{2}]", str, row, colm);
}
}
}
uma goto
instrução é usada para transferir o controle de um escopo aninhado.a goto
statement is used to transfer control out of a nested scope.
O destino de uma goto case
instrução é a lista de instruções na instrução de circunscrição imediatamente switch
(a instrução switch), que contém um case
rótulo com o valor constante fornecido.The target of a goto case
statement is the statement list in the immediately enclosing switch
statement (The switch statement), which contains a case
label with the given constant value. Se a goto case
instrução não estiver delimitada por uma switch
instrução, se a constant_expression não for implicitamente conversível (conversões implícitas) para o tipo regulador da instrução de circunscrição mais próxima switch
, ou se a instrução delimitadora mais próxima switch
não contiver um case
rótulo com o valor constante fornecido, ocorrerá um erro em tempo de compilação.If the goto case
statement is not enclosed by a switch
statement, if the constant_expression is not implicitly convertible (Implicit conversions) to the governing type of the nearest enclosing switch
statement, or if the nearest enclosing switch
statement does not contain a case
label with the given constant value, a compile-time error occurs.
O destino de uma goto default
instrução é a lista de instruções na instrução de circunscrição imediatamente switch
(a instrução switch), que contém um default
rótulo.The target of a goto default
statement is the statement list in the immediately enclosing switch
statement (The switch statement), which contains a default
label. Se a goto default
instrução não estiver delimitada por uma switch
instrução ou se a instrução delimitadora mais próxima switch
não contiver um default
rótulo, ocorrerá um erro em tempo de compilação.If the goto default
statement is not enclosed by a switch
statement, or if the nearest enclosing switch
statement does not contain a default
label, a compile-time error occurs.
Uma goto
instrução não pode sair de um finally
bloco (a instrução try).A goto
statement cannot exit a finally
block (The try statement). Quando uma goto
instrução ocorre dentro de um finally
bloco, o destino da goto
instrução deve estar dentro do mesmo finally
bloco ou ocorre um erro de tempo de compilação.When a goto
statement occurs within a finally
block, the target of the goto
statement must be within the same finally
block, or otherwise a compile-time error occurs.
Uma goto
instrução é executada da seguinte maneira:A goto
statement is executed as follows:
- Se a
goto
instrução sair de um ou maistry
blocos comfinally
blocos associados, o controle será transferido inicialmente para ofinally
bloco da instrução mais internatry
.If thegoto
statement exits one or moretry
blocks with associatedfinally
blocks, control is initially transferred to thefinally
block of the innermosttry
statement. Quando e se o controle atingir o ponto de extremidade de umfinally
bloco, o controle será transferido para ofinally
bloco da próxima instrução de circunscriçãotry
.When and if control reaches the end point of afinally
block, control is transferred to thefinally
block of the next enclosingtry
statement. Esse processo é repetido até que osfinally
blocos de todas as instruções intermediáriastry
tenham sido executados.This process is repeated until thefinally
blocks of all interveningtry
statements have been executed. - O controle é transferido para o destino da
goto
instrução.Control is transferred to the target of thegoto
statement.
Como uma goto
instrução transfere incondicionalmente o controle em outro lugar, o ponto de extremidade de uma goto
instrução nunca é acessível.Because a goto
statement unconditionally transfers control elsewhere, the end point of a goto
statement is never reachable.
A instrução returnThe return statement
A return
instrução retorna o controle para o chamador atual da função na qual a return
instrução é exibida.The return
statement returns control to the current caller of the function in which the return
statement appears.
return_statement
: 'return' expression? ';'
;
Uma return
instrução sem expressão só pode ser usada em um membro de função que não Compute um valor, ou seja, um método com o tipo de resultado (corpo do método) void
, o set
acessador de uma propriedade ou um indexador, os add
remove
acessadores de um evento, um construtor de instância, um construtor estático ou um destruidor.A return
statement with no expression can be used only in a function member that does not compute a value, that is, a method with the result type (Method body) void
, the set
accessor of a property or indexer, the add
and remove
accessors of an event, an instance constructor, a static constructor, or a destructor.
Uma return
instrução com uma expressão só pode ser usada em um membro de função que computa um valor, ou seja, um método com um tipo de resultado não void, o get
acessador de uma propriedade ou um indexador ou um operador definido pelo usuário.A return
statement with an expression can only be used in a function member that computes a value, that is, a method with a non-void result type, the get
accessor of a property or indexer, or a user-defined operator. Uma conversão implícita (conversões implícitas) deve existir do tipo da expressão para o tipo de retorno do membro da função que a contém.An implicit conversion (Implicit conversions) must exist from the type of the expression to the return type of the containing function member.
Instruções de retorno também podem ser usadas no corpo de expressões de função anônimas (expressões de função anônimas) e participam da determinação de quais conversões existem para essas funções.Return statements can also be used in the body of anonymous function expressions (Anonymous function expressions), and participate in determining which conversions exist for those functions.
É um erro de tempo de compilação para return
que uma instrução apareça em um finally
bloco (a instrução try).It is a compile-time error for a return
statement to appear in a finally
block (The try statement).
Uma return
instrução é executada da seguinte maneira:A return
statement is executed as follows:
- Se a
return
instrução especificar uma expressão, a expressão será avaliada e o valor resultante será convertido no tipo de retorno da função que a contém por uma conversão implícita.If thereturn
statement specifies an expression, the expression is evaluated and the resulting value is converted to the return type of the containing function by an implicit conversion. O resultado da conversão se torna o valor de resultado produzido pela função.The result of the conversion becomes the result value produced by the function. - Se a
return
instrução estiver entre um ou maistry
blocos oucatch
com blocos associadosfinally
, o controle será transferido inicialmente para ofinally
bloco da instrução mais internatry
.If thereturn
statement is enclosed by one or moretry
orcatch
blocks with associatedfinally
blocks, control is initially transferred to thefinally
block of the innermosttry
statement. Quando e se o controle atingir o ponto de extremidade de umfinally
bloco, o controle será transferido para ofinally
bloco da próxima instrução de circunscriçãotry
.When and if control reaches the end point of afinally
block, control is transferred to thefinally
block of the next enclosingtry
statement. Esse processo é repetido até que osfinally
blocos de todas as instruções de circunscriçãotry
tenham sido executados.This process is repeated until thefinally
blocks of all enclosingtry
statements have been executed. - Se a função que a contém não for uma função assíncrona, o controle será retornado para o chamador da função recipiente junto com o valor de resultado, se houver.If the containing function is not an async function, control is returned to the caller of the containing function along with the result value, if any.
- Se a função que a contém for uma função assíncrona, o controle será retornado para o chamador atual e o valor de resultado, se houver, será registrado na tarefa de retorno conforme descrito em (interfaces do enumerador).If the containing function is an async function, control is returned to the current caller, and the result value, if any, is recorded in the return task as described in (Enumerator interfaces).
Como uma return
instrução transfere incondicionalmente o controle em outro lugar, o ponto de extremidade de uma return
instrução nunca é acessível.Because a return
statement unconditionally transfers control elsewhere, the end point of a return
statement is never reachable.
A instrução ThrowThe throw statement
A instrução throw
lança uma exceção.The throw
statement throws an exception.
throw_statement
: 'throw' expression? ';'
;
Uma throw
instrução com uma expressão lança o valor produzido avaliando a expressão.A throw
statement with an expression throws the value produced by evaluating the expression. A expressão deve indicar um valor do tipo de classe System.Exception
, de um tipo de classe que deriva de System.Exception
ou de um tipo de parâmetro de tipo que tenha System.Exception
(ou uma subclasse dele) como sua classe base efetiva.The expression must denote a value of the class type System.Exception
, of a class type that derives from System.Exception
or of a type parameter type that has System.Exception
(or a subclass thereof) as its effective base class. Se a avaliação da expressão produzir null
, um System.NullReferenceException
será lançado em vez disso.If evaluation of the expression produces null
, a System.NullReferenceException
is thrown instead.
Uma throw
instrução sem expressão só pode ser usada em um catch
bloco, caso em que a instrução relança a exceção que está sendo manipulada por esse bloco no momento catch
.A throw
statement with no expression can be used only in a catch
block, in which case that statement re-throws the exception that is currently being handled by that catch
block.
Como uma throw
instrução transfere incondicionalmente o controle em outro lugar, o ponto de extremidade de uma throw
instrução nunca é acessível.Because a throw
statement unconditionally transfers control elsewhere, the end point of a throw
statement is never reachable.
Quando uma exceção é lançada, o controle é transferido para a primeira catch
cláusula em uma instrução delimitadora try
que pode manipular a exceção.When an exception is thrown, control is transferred to the first catch
clause in an enclosing try
statement that can handle the exception. O processo que ocorre desde o ponto da exceção sendo gerada para o ponto de transferência do controle para um manipulador de exceção adequado é conhecido como *propagação de exceção _.The process that takes place from the point of the exception being thrown to the point of transferring control to a suitable exception handler is known as *exception propagation _. A propagação de uma exceção consiste em avaliar repetidamente as etapas a seguir até que uma catch
cláusula correspondente à exceção seja encontrada.Propagation of an exception consists of repeatedly evaluating the following steps until a catch
clause that matches the exception is found. Nesta descrição, o _ ponto de extensão* é inicialmente o local no qual a exceção é lançada.In this description, the _ throw point* is initially the location at which the exception is thrown.
No membro da função atual, cada
try
instrução que se aproxima do ponto de lançamento é examinada.In the current function member, eachtry
statement that encloses the throw point is examined. Para cada instruçãoS
, começando com a instrução mais internatry
e terminando com a instrução mais externatry
, as etapas a seguir são avaliadas:For each statementS
, starting with the innermosttry
statement and ending with the outermosttry
statement, the following steps are evaluated:Se o
try
bloco deS
fechar o ponto de lançamento e se S tiver uma ou maiscatch
cláusulas, ascatch
cláusulas serão examinadas em ordem de aparência para localizar um manipulador adequado para a exceção, de acordo com as regras especificadas na seção instrução try.If thetry
block ofS
encloses the throw point and if S has one or morecatch
clauses, thecatch
clauses are examined in order of appearance to locate a suitable handler for the exception, according to the rules specified in Section The try statement. Se umacatch
cláusula correspondente estiver localizada, a propagação de exceção será concluída transferindo o controle para o bloco dessacatch
cláusula.If a matchingcatch
clause is located, the exception propagation is completed by transferring control to the block of thatcatch
clause.Caso contrário, se o
try
bloco ou umcatch
bloco deS
fechar o ponto de lançamento e seS
tiver umfinally
bloco, o controle será transferido para ofinally
bloco.Otherwise, if thetry
block or acatch
block ofS
encloses the throw point and ifS
has afinally
block, control is transferred to thefinally
block. Se ofinally
bloco lançar outra exceção, o processamento da exceção atual será encerrado.If thefinally
block throws another exception, processing of the current exception is terminated. Caso contrário, quando o controle atingir o ponto de extremidade dofinally
bloco, o processamento da exceção atual será continuado.Otherwise, when control reaches the end point of thefinally
block, processing of the current exception is continued.
Se um manipulador de exceção não estiver localizado na invocação de função atual, a invocação de função será encerrada e uma das seguintes situações ocorrerá:If an exception handler was not located in the current function invocation, the function invocation is terminated, and one of the following occurs:
Se a função atual for não Async, as etapas acima serão repetidas para o chamador da função com um ponto de geração correspondente à instrução da qual o membro da função foi invocado.If the current function is non-async, the steps above are repeated for the caller of the function with a throw point corresponding to the statement from which the function member was invoked.
Se a função atual for Async e retornando Task, a exceção será registrada na tarefa de retorno, que será colocada em um estado falho ou cancelado, conforme descrito em interfaces do enumerador.If the current function is async and task-returning, the exception is recorded in the return task, which is put into a faulted or cancelled state as described in Enumerator interfaces.
Se a função atual for Async e void-retornando, o contexto de sincronização do thread atual será notificado conforme descrito em interfaces enumeráveis.If the current function is async and void-returning, the synchronization context of the current thread is notified as described in Enumerable interfaces.
Se o processamento de exceções terminar todas as invocações de membro de função no thread atual, indicando que o thread não tem nenhum manipulador para a exceção, o thread será encerrado.If the exception processing terminates all function member invocations in the current thread, indicating that the thread has no handler for the exception, then the thread is itself terminated. O impacto dessa terminação é definido pela implementação.The impact of such termination is implementation-defined.
A instrução tryThe try statement
A try
instrução fornece um mecanismo para capturar exceções que ocorrem durante a execução de um bloco.The try
statement provides a mechanism for catching exceptions that occur during execution of a block. Além disso, a try
instrução fornece a capacidade de especificar um bloco de código que é sempre executado quando o controle sai da try
instrução.Furthermore, the try
statement provides the ability to specify a block of code that is always executed when control leaves the try
statement.
try_statement
: 'try' block catch_clause+
| 'try' block finally_clause
| 'try' block catch_clause+ finally_clause
;
catch_clause
: 'catch' exception_specifier? exception_filter? block
;
exception_specifier
: '(' type identifier? ')'
;
exception_filter
: 'when' '(' expression ')'
;
finally_clause
: 'finally' block
;
Há três formas de instruções possíveis try
:There are three possible forms of try
statements:
- Um
try
bloco seguido por um ou maiscatch
blocos.Atry
block followed by one or morecatch
blocks. - Um
try
bloco seguido por umfinally
bloco.Atry
block followed by afinally
block. - Um
try
bloco seguido por um ou maiscatch
blocos seguidos por umfinally
bloco.Atry
block followed by one or morecatch
blocks followed by afinally
block.
Quando uma catch
cláusula Especifica um exception_specifier, o tipo deve ser System.Exception
, um tipo que deriva de System.Exception
ou um tipo de parâmetro de tipo que tenha System.Exception
(ou uma subclasse dele) como sua classe base em vigor.When a catch
clause specifies an exception_specifier, the type must be System.Exception
, a type that derives from System.Exception
or a type parameter type that has System.Exception
(or a subclass thereof) as its effective base class.
Quando uma catch
cláusula Especifica um exception_specifier com um identificador, uma variável de exceção* _ do nome e tipo fornecido é declarada.When a catch
clause specifies both an exception_specifier with an identifier, an *exception variable _ of the given name and type is declared. A variável de exceção corresponde a uma variável local com um escopo que se estende pela catch
cláusula.The exception variable corresponds to a local variable with a scope that extends over the catch
clause. Durante a execução do _exception_filter * e do bloco, a variável de exceção representa a exceção que está sendo manipulada no momento.During execution of the _exception_filter* and block, the exception variable represents the exception currently being handled. Para fins de verificação de atribuição definitiva, a variável de exceção é considerada definitivamente atribuída em seu escopo inteiro.For purposes of definite assignment checking, the exception variable is considered definitely assigned in its entire scope.
A menos que uma catch
cláusula inclua um nome de variável de exceção, é impossível acessar o objeto de exceção no filtro e no catch
bloco.Unless a catch
clause includes an exception variable name, it is impossible to access the exception object in the filter and catch
block.
Uma catch
cláusula que não especifica um exception_specifier é chamada de cláusula geral catch
.A catch
clause that does not specify an exception_specifier is called a general catch
clause.
Algumas linguagens de programação podem dar suporte a exceções que não podem ser representes como um objeto derivado de System.Exception
, embora essas exceções nunca pudessem ser geradas pelo código C#.Some programming languages may support exceptions that are not representable as an object derived from System.Exception
, although such exceptions could never be generated by C# code. Uma catch
cláusula geral pode ser usada para capturar essas exceções.A general catch
clause may be used to catch such exceptions. Portanto, uma catch
cláusula geral é semanticamente diferente de uma que especifica o tipo System.Exception
, pois a primeira também pode detectar exceções de outras linguagens.Thus, a general catch
clause is semantically different from one that specifies the type System.Exception
, in that the former may also catch exceptions from other languages.
Para localizar um manipulador de uma exceção, as catch
cláusulas são examinadas em ordem lexical.In order to locate a handler for an exception, catch
clauses are examined in lexical order. Se uma catch
cláusula Especifica um tipo, mas nenhum filtro de exceção, é um erro de tempo de compilação para uma catch
cláusula posterior na mesma try
instrução para especificar um tipo que seja igual ou derivado desse tipo.If a catch
clause specifies a type but no exception filter, it is a compile-time error for a later catch
clause in the same try
statement to specify a type that is the same as, or is derived from, that type. Se uma catch
cláusula não especificar nenhum tipo e nenhum filtro, ela deverá ser a última catch
cláusula para essa try
instrução.If a catch
clause specifies no type and no filter, it must be the last catch
clause for that try
statement.
Dentro de um catch
bloco, uma throw
instrução (a instrução Throw) sem expressão pode ser usada para relançar a exceção que foi detectada pelo catch
bloco.Within a catch
block, a throw
statement (The throw statement) with no expression can be used to re-throw the exception that was caught by the catch
block. As atribuições a uma variável de exceção não alteram a exceção gerada novamente.Assignments to an exception variable do not alter the exception that is re-thrown.
No exemploIn the example
using System;
class Test
{
static void F() {
try {
G();
}
catch (Exception e) {
Console.WriteLine("Exception in F: " + e.Message);
e = new Exception("F");
throw; // re-throw
}
}
static void G() {
throw new Exception("G");
}
static void Main() {
try {
F();
}
catch (Exception e) {
Console.WriteLine("Exception in Main: " + e.Message);
}
}
}
o método F
captura uma exceção, grava algumas informações de diagnóstico no console, altera a variável de exceção e lança novamente a exceção.the method F
catches an exception, writes some diagnostic information to the console, alters the exception variable, and re-throws the exception. A exceção gerada novamente é a exceção original, portanto, a saída produzida é:The exception that is re-thrown is the original exception, so the output produced is:
Exception in F: G
Exception in Main: G
Se o primeiro bloco catch tiver sido lançado e
em vez de relançar a exceção atual, a saída produzida seria a seguinte:If the first catch block had thrown e
instead of rethrowing the current exception, the output produced would be as follows:
Exception in F: G
Exception in Main: F
É um erro de tempo de compilação para uma break
continue
instrução, ou goto
para transferir o controle de um finally
bloco.It is a compile-time error for a break
, continue
, or goto
statement to transfer control out of a finally
block. Quando uma break
continue
instrução,, ou goto
ocorre em um finally
bloco, o destino da instrução deve estar dentro do mesmo finally
bloco ou, caso contrário, ocorrerá um erro de tempo de compilação.When a break
, continue
, or goto
statement occurs in a finally
block, the target of the statement must be within the same finally
block, or otherwise a compile-time error occurs.
É um erro de tempo de compilação para return
que uma instrução ocorra em um finally
bloco.It is a compile-time error for a return
statement to occur in a finally
block.
Uma try
instrução é executada da seguinte maneira:A try
statement is executed as follows:
O controle é transferido para o
try
bloco.Control is transferred to thetry
block.Quando e se o controle atingir o ponto de extremidade do
try
bloco:When and if control reaches the end point of thetry
block:- Se a
try
instrução tiver umfinally
bloco, ofinally
bloco será executado.If thetry
statement has afinally
block, thefinally
block is executed. - O controle é transferido para o ponto de extremidade da
try
instrução.Control is transferred to the end point of thetry
statement.
- Se a
Se uma exceção for propagada para a
try
instrução durante a execução dotry
bloco:If an exception is propagated to thetry
statement during execution of thetry
block:- As
catch
cláusulas, se houver, são examinadas em ordem de aparência para localizar um manipulador adequado para a exceção.Thecatch
clauses, if any, are examined in order of appearance to locate a suitable handler for the exception. Se umacatch
cláusula não especificar um tipo, ou especificar o tipo de exceção ou um tipo base do tipo de exceção:If acatch
clause does not specify a type, or specifies the exception type or a base type of the exception type:- Se a
catch
cláusula declarar uma variável de exceção, o objeto de exceção será atribuído à variável de exceção.If thecatch
clause declares an exception variable, the exception object is assigned to the exception variable. - Se a
catch
cláusula declarar um filtro de exceção, o filtro será avaliado.If thecatch
clause declares an exception filter, the filter is evaluated. Se ele for avaliado comofalse
, a cláusula catch não será uma correspondência e a pesquisa continuará em todas ascatch
cláusulas subsequentes para um manipulador adequado.If it evaluates tofalse
, the catch clause is not a match, and the search continues through any subsequentcatch
clauses for a suitable handler. - Caso contrário, a
catch
cláusula será considerada uma correspondência e o controle será transferido para ocatch
bloco correspondente.Otherwise, thecatch
clause is considered a match, and control is transferred to the matchingcatch
block. - Quando e se o controle atingir o ponto de extremidade do
catch
bloco:When and if control reaches the end point of thecatch
block:- Se a
try
instrução tiver umfinally
bloco, ofinally
bloco será executado.If thetry
statement has afinally
block, thefinally
block is executed. - O controle é transferido para o ponto de extremidade da
try
instrução.Control is transferred to the end point of thetry
statement.
- Se a
- Se uma exceção for propagada para a
try
instrução durante a execução docatch
bloco:If an exception is propagated to thetry
statement during execution of thecatch
block:- Se a
try
instrução tiver umfinally
bloco, ofinally
bloco será executado.If thetry
statement has afinally
block, thefinally
block is executed. - A exceção é propagada para a próxima instrução de circunscrição
try
.The exception is propagated to the next enclosingtry
statement.
- Se a
- Se a
- Se a
try
instrução não tivercatch
cláusulas ou se nenhumacatch
cláusula corresponder à exceção:If thetry
statement has nocatch
clauses or if nocatch
clause matches the exception:- Se a
try
instrução tiver umfinally
bloco, ofinally
bloco será executado.If thetry
statement has afinally
block, thefinally
block is executed. - A exceção é propagada para a próxima instrução de circunscrição
try
.The exception is propagated to the next enclosingtry
statement.
- Se a
- As
As instruções de um finally
bloco são sempre executadas quando o controle sai de uma try
instrução.The statements of a finally
block are always executed when control leaves a try
statement. Isso é verdadeiro se a transferência de controle ocorre como resultado da execução normal, como resultado da execução de uma break
continue
instrução,, goto
ou return
, ou como resultado da propagação de uma exceção fora da try
instrução.This is true whether the control transfer occurs as a result of normal execution, as a result of executing a break
, continue
, goto
, or return
statement, or as a result of propagating an exception out of the try
statement.
Se uma exceção for lançada durante a execução de um finally
bloco e não for detectada no mesmo bloco finally, a exceção será propagada para a próxima instrução de circunscrição try
.If an exception is thrown during execution of a finally
block, and is not caught within the same finally block, the exception is propagated to the next enclosing try
statement. Se outra exceção estava no processo de ser propagada, essa exceção é perdida.If another exception was in the process of being propagated, that exception is lost. O processo de propagação de uma exceção é abordado mais detalhadamente na descrição da throw
instrução (a instrução Throw).The process of propagating an exception is discussed further in the description of the throw
statement (The throw statement).
O try
bloco de uma try
instrução estará acessível se a try
instrução puder ser acessada.The try
block of a try
statement is reachable if the try
statement is reachable.
Um catch
bloco de uma try
instrução pode ser acessado se a try
instrução estiver acessível.A catch
block of a try
statement is reachable if the try
statement is reachable.
O finally
bloco de uma try
instrução estará acessível se a try
instrução puder ser acessada.The finally
block of a try
statement is reachable if the try
statement is reachable.
O ponto de extremidade de uma try
instrução estará acessível se as seguintes opções forem verdadeiras:The end point of a try
statement is reachable if both of the following are true:
- O ponto de extremidade do
try
bloco é acessível ou o ponto de extremidade de pelo menos umcatch
bloco está acessível.The end point of thetry
block is reachable or the end point of at least onecatch
block is reachable. - Se um
finally
bloco estiver presente, o ponto final dofinally
bloco estará acessível.If afinally
block is present, the end point of thefinally
block is reachable.
As instruções marcadas e desmarcadasThe checked and unchecked statements
As checked
unchecked
instruções e são usadas para controlar o contexto de verificação de estouro para operações aritméticas de tipo integral e conversões.The checked
and unchecked
statements are used to control the overflow checking context for integral-type arithmetic operations and conversions.
checked_statement
: 'checked' block
;
unchecked_statement
: 'unchecked' block
;
A checked
instrução faz com que todas as expressões no bloco sejam avaliadas em um contexto selecionado, e a unchecked
instrução faz com que todas as expressões no bloco sejam avaliadas em um contexto desmarcado.The checked
statement causes all expressions in the block to be evaluated in a checked context, and the unchecked
statement causes all expressions in the block to be evaluated in an unchecked context.
As checked
unchecked
instruções e são precisamente equivalentes aos checked
unchecked
operadores e (os operadores marcados e desmarcados), exceto que operam em blocos em vez de expressões.The checked
and unchecked
statements are precisely equivalent to the checked
and unchecked
operators (The checked and unchecked operators), except that they operate on blocks instead of expressions.
A instrução lockThe lock statement
A lock
instrução Obtém o bloqueio de mutual-exclusion para um determinado objeto, executa uma instrução e, em seguida, libera o bloqueio.The lock
statement obtains the mutual-exclusion lock for a given object, executes a statement, and then releases the lock.
lock_statement
: 'lock' '(' expression ')' embedded_statement
;
A expressão de uma lock
instrução deve indicar um valor de um tipo conhecido como um reference_type.The expression of a lock
statement must denote a value of a type known to be a reference_type. Nenhuma conversão de Boxing implícita (conversões Boxing) é executada para a expressão de uma lock
instrução e, portanto, é um erro de tempo de compilação para a expressão denotar um valor de um value_type.No implicit boxing conversion (Boxing conversions) is ever performed for the expression of a lock
statement, and thus it is a compile-time error for the expression to denote a value of a value_type.
Uma lock
instrução do formulárioA lock
statement of the form
lock (x) ...
em que x
é uma expressão de uma reference_type, é precisamente equivalente awhere x
is an expression of a reference_type, is precisely equivalent to
bool __lockWasTaken = false;
try {
System.Threading.Monitor.Enter(x, ref __lockWasTaken);
...
}
finally {
if (__lockWasTaken) System.Threading.Monitor.Exit(x);
}
exceto que x
é avaliado apenas uma vez.except that x
is only evaluated once.
Enquanto um bloqueio de exclusão mútua é mantido, o código em execução no mesmo thread de execução também pode obter e liberar o bloqueio.While a mutual-exclusion lock is held, code executing in the same execution thread can also obtain and release the lock. No entanto, o código em execução em outros threads é impedido de obter o bloqueio até que o bloqueio seja liberado.However, code executing in other threads is blocked from obtaining the lock until the lock is released.
O bloqueio System.Type
de objetos para sincronizar o acesso a dados estáticos não é recomendado.Locking System.Type
objects in order to synchronize access to static data is not recommended. Outro código pode bloquear no mesmo tipo, o que pode resultar em deadlock.Other code might lock on the same type, which can result in deadlock. Uma abordagem melhor é sincronizar o acesso a dados estáticos bloqueando um objeto estático privado.A better approach is to synchronize access to static data by locking a private static object. Por exemplo:For example:
class Cache
{
private static readonly object synchronizationObject = new object();
public static void Add(object x) {
lock (Cache.synchronizationObject) {
...
}
}
public static void Remove(object x) {
lock (Cache.synchronizationObject) {
...
}
}
}
A instrução usingThe using statement
A using
instrução Obtém um ou mais recursos, executa uma instrução e, em seguida, descarta o recurso.The using
statement obtains one or more resources, executes a statement, and then disposes of the resource.
using_statement
: 'using' '(' resource_acquisition ')' embedded_statement
;
resource_acquisition
: local_variable_declaration
| expression
;
Um recurso é uma classe ou struct que implementa System.IDisposable
, que inclui um único método sem parâmetros chamado Dispose
.A resource is a class or struct that implements System.IDisposable
, which includes a single parameterless method named Dispose
. O código que está usando um recurso pode chamar Dispose
para indicar que o recurso não é mais necessário.Code that is using a resource can call Dispose
to indicate that the resource is no longer needed. Se Dispose
não for chamado, a eliminação automática eventualmente ocorrerá como consequência da coleta de lixo.If Dispose
is not called, then automatic disposal eventually occurs as a consequence of garbage collection.
Se a forma de resource_acquisition for local_variable_declaration , o tipo de local_variable_declaration deverá ser dynamic
ou um tipo que possa ser convertido implicitamente em System.IDisposable
.If the form of resource_acquisition is local_variable_declaration then the type of the local_variable_declaration must be either dynamic
or a type that can be implicitly converted to System.IDisposable
. Se a forma de resource_acquisition for expression , essa expressão deverá ser conversível implicitamente System.IDisposable
.If the form of resource_acquisition is expression then this expression must be implicitly convertible to System.IDisposable
.
Variáveis locais declaradas em uma resource_acquisition são somente leitura e devem incluir um inicializador.Local variables declared in a resource_acquisition are read-only, and must include an initializer. Ocorrerá um erro de tempo de compilação se a instrução inserida tentar modificar essas variáveis locais (por meio de atribuição ou os ++
--
operadores e), pegar o endereço delas ou passá-las como ref
out
parâmetros ou.A compile-time error occurs if the embedded statement attempts to modify these local variables (via assignment or the ++
and --
operators) , take the address of them, or pass them as ref
or out
parameters.
Uma using
instrução é convertida em três partes: aquisição, uso e alienação.A using
statement is translated into three parts: acquisition, usage, and disposal. O uso do recurso é implicitamente incluído em uma try
instrução que inclui uma finally
cláusula.Usage of the resource is implicitly enclosed in a try
statement that includes a finally
clause. Essa finally
cláusula descarta o recurso.This finally
clause disposes of the resource. Se um null
recurso for adquirido, nenhuma chamada para Dispose
será feita e nenhuma exceção será gerada.If a null
resource is acquired, then no call to Dispose
is made, and no exception is thrown. Se o recurso for do tipo dynamic
, ele será convertido dinamicamente por meio de uma conversão dinâmica implícita (conversões dinâmicas implícitas) IDisposable
durante a aquisição para garantir que a conversão seja bem-sucedida antes do uso e da alienação.If the resource is of type dynamic
it is dynamically converted through an implicit dynamic conversion (Implicit dynamic conversions) to IDisposable
during acquisition in order to ensure that the conversion is successful before the usage and disposal.
Uma using
instrução do formulárioA using
statement of the form
using (ResourceType resource = expression) statement
corresponde a uma das três expansões possíveis.corresponds to one of three possible expansions. Quando ResourceType
é um tipo de valor não anulável, a expansão éWhen ResourceType
is a non-nullable value type, the expansion is
{
ResourceType resource = expression;
try {
statement;
}
finally {
((IDisposable)resource).Dispose();
}
}
Caso contrário, quando ResourceType
for um tipo de valor anulável ou um tipo de referência diferente de dynamic
, a expansão seráOtherwise, when ResourceType
is a nullable value type or a reference type other than dynamic
, the expansion is
{
ResourceType resource = expression;
try {
statement;
}
finally {
if (resource != null) ((IDisposable)resource).Dispose();
}
}
Caso contrário, quando ResourceType
for dynamic
, a expansão seráOtherwise, when ResourceType
is dynamic
, the expansion is
{
ResourceType resource = expression;
IDisposable d = (IDisposable)resource;
try {
statement;
}
finally {
if (d != null) d.Dispose();
}
}
Em qualquer expansão, a resource
variável é somente leitura na instrução incorporada, e a d
variável é inacessível em, e invisível para, a instrução inserida.In either expansion, the resource
variable is read-only in the embedded statement, and the d
variable is inaccessible in, and invisible to, the embedded statement.
Uma implementação tem permissão para implementar uma determinada instrução using de forma diferente, por exemplo, por motivos de desempenho, desde que o comportamento seja consistente com a expansão acima.An implementation is permitted to implement a given using-statement differently, e.g. for performance reasons, as long as the behavior is consistent with the above expansion.
Uma using
instrução do formulárioA using
statement of the form
using (expression) statement
tem as mesmas três expansões possíveis.has the same three possible expansions. Nesse caso ResourceType
, é implicitamente o tipo de tempo de compilação do expression
, se tiver um.In this case ResourceType
is implicitly the compile-time type of the expression
, if it has one. Caso contrário, a IDisposable
própria interface será usada como o ResourceType
.Otherwise the interface IDisposable
itself is used as the ResourceType
. A resource
variável é inacessível em, e invisível para, a instrução inserida.The resource
variable is inaccessible in, and invisible to, the embedded statement.
Quando um resource_acquisition usa a forma de um local_variable_declaration, é possível adquirir vários recursos de um determinado tipo.When a resource_acquisition takes the form of a local_variable_declaration, it is possible to acquire multiple resources of a given type. Uma using
instrução do formulárioA using
statement of the form
using (ResourceType r1 = e1, r2 = e2, ..., rN = eN) statement
é precisamente equivalente a uma sequência de instruções aninhadas using
:is precisely equivalent to a sequence of nested using
statements:
using (ResourceType r1 = e1)
using (ResourceType r2 = e2)
...
using (ResourceType rN = eN)
statement
O exemplo a seguir cria um arquivo chamado log.txt
e grava duas linhas de texto no arquivo.The example below creates a file named log.txt
and writes two lines of text to the file. Em seguida, o exemplo abre o mesmo arquivo para ler e copiar as linhas de texto contidas para o console.The example then opens that same file for reading and copies the contained lines of text to the console.
using System;
using System.IO;
class Test
{
static void Main() {
using (TextWriter w = File.CreateText("log.txt")) {
w.WriteLine("This is line one");
w.WriteLine("This is line two");
}
using (TextReader r = File.OpenText("log.txt")) {
string s;
while ((s = r.ReadLine()) != null) {
Console.WriteLine(s);
}
}
}
}
Como as TextWriter
TextReader
classes e implementam a IDisposable
interface, o exemplo pode usar using
instruções para garantir que o arquivo subjacente seja fechado corretamente seguindo as operações de gravação ou leitura.Since the TextWriter
and TextReader
classes implement the IDisposable
interface, the example can use using
statements to ensure that the underlying file is properly closed following the write or read operations.
A instrução yieldThe yield statement
A yield
instrução é usada em um bloco do iterador (blocos) para gerar um valor para o objeto do enumerador (objetos do enumerador) ou objeto enumerável (objetos enumeráveis) de um iterador ou para sinalizar o final da iteração.The yield
statement is used in an iterator block (Blocks) to yield a value to the enumerator object (Enumerator objects) or enumerable object (Enumerable objects) of an iterator or to signal the end of the iteration.
yield_statement
: 'yield' 'return' expression ';'
| 'yield' 'break' ';'
;
yield
Não é uma palavra reservada; Ele tem um significado especial somente quando usado imediatamente antes de uma return
break
palavra-chave ou.yield
is not a reserved word; it has special meaning only when used immediately before a return
or break
keyword. Em outros contextos, yield
pode ser usado como um identificador.In other contexts, yield
can be used as an identifier.
Há várias restrições sobre onde uma yield
instrução pode aparecer, conforme descrito a seguir.There are several restrictions on where a yield
statement can appear, as described in the following.
- É um erro de tempo de compilação para uma
yield
instrução (de qualquer forma) aparecer fora de um method_body, operator_body ou accessor_bodyIt is a compile-time error for ayield
statement (of either form) to appear outside a method_body, operator_body or accessor_body - É um erro de tempo de compilação para uma
yield
instrução (de qualquer forma) aparecer dentro de uma função anônima.It is a compile-time error for ayield
statement (of either form) to appear inside an anonymous function. - É um erro de tempo de compilação para uma
yield
instrução (de qualquer forma) aparecer nafinally
cláusula de umatry
instrução.It is a compile-time error for ayield
statement (of either form) to appear in thefinally
clause of atry
statement. - É um erro de tempo de compilação para uma
yield return
instrução aparecer em qualquer lugar em umatry
instrução que contenha qualquercatch
cláusula.It is a compile-time error for ayield return
statement to appear anywhere in atry
statement that contains anycatch
clauses.
O exemplo a seguir mostra alguns usos válidos e inválidos de yield
instruções.The following example shows some valid and invalid uses of yield
statements.
delegate IEnumerable<int> D();
IEnumerator<int> GetEnumerator() {
try {
yield return 1; // Ok
yield break; // Ok
}
finally {
yield return 2; // Error, yield in finally
yield break; // Error, yield in finally
}
try {
yield return 3; // Error, yield return in try...catch
yield break; // Ok
}
catch {
yield return 4; // Error, yield return in try...catch
yield break; // Ok
}
D d = delegate {
yield return 5; // Error, yield in an anonymous function
};
}
int MyMethod() {
yield return 1; // Error, wrong return type for an iterator block
}
Uma conversão implícita (conversões implícitas) deve existir do tipo da expressão na yield return
instrução para o tipo yield (tipo yield) do iterador.An implicit conversion (Implicit conversions) must exist from the type of the expression in the yield return
statement to the yield type (Yield type) of the iterator.
Uma yield return
instrução é executada da seguinte maneira:A yield return
statement is executed as follows:
- A expressão fornecida na instrução é avaliada, implicitamente convertida para o tipo yield e atribuída à
Current
Propriedade do objeto Enumerator.The expression given in the statement is evaluated, implicitly converted to the yield type, and assigned to theCurrent
property of the enumerator object. - A execução do bloco do iterador está suspensa.Execution of the iterator block is suspended. Se a
yield return
instrução estiver dentro de um ou maistry
blocos, osfinally
blocos associados não serão executados neste momento.If theyield return
statement is within one or moretry
blocks, the associatedfinally
blocks are not executed at this time. - O
MoveNext
método do objeto enumerador retornatrue
para seu chamador, indicando que o objeto enumerador foi avançado com êxito para o próximo item.TheMoveNext
method of the enumerator object returnstrue
to its caller, indicating that the enumerator object successfully advanced to the next item.
A próxima chamada para o método do objeto enumerador MoveNext
retoma a execução do bloco iterador de onde ele foi suspenso pela última vez.The next call to the enumerator object's MoveNext
method resumes execution of the iterator block from where it was last suspended.
Uma yield break
instrução é executada da seguinte maneira:A yield break
statement is executed as follows:
- Se a
yield break
instrução estiver contida em um ou maistry
blocos comfinally
blocos associados, o controle será transferido inicialmente para ofinally
bloco da instrução mais internatry
.If theyield break
statement is enclosed by one or moretry
blocks with associatedfinally
blocks, control is initially transferred to thefinally
block of the innermosttry
statement. Quando e se o controle atingir o ponto de extremidade de umfinally
bloco, o controle será transferido para ofinally
bloco da próxima instrução de circunscriçãotry
.When and if control reaches the end point of afinally
block, control is transferred to thefinally
block of the next enclosingtry
statement. Esse processo é repetido até que osfinally
blocos de todas as instruções de circunscriçãotry
tenham sido executados.This process is repeated until thefinally
blocks of all enclosingtry
statements have been executed. - O controle é retornado para o chamador do bloco do iterador.Control is returned to the caller of the iterator block. Esse é o
MoveNext
método ouDispose
método do objeto enumerador.This is either theMoveNext
method orDispose
method of the enumerator object.
Como uma yield break
instrução transfere incondicionalmente o controle em outro lugar, o ponto de extremidade de uma yield break
instrução nunca é acessível.Because a yield break
statement unconditionally transfers control elsewhere, the end point of a yield break
statement is never reachable.