IstruzioniStatements

C#fornisce una serie di istruzioni.C# provides a variety of statements. La maggior parte di queste istruzioni sarà familiare per gli sviluppatori che hanno programmato in C++C e.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
    ;

Il embedded_statement non terminale viene usato per le istruzioni visualizzate all'interno di altre istruzioni.The embedded_statement nonterminal is used for statements that appear within other statements. L'utilizzo di embedded_statement anziché di un' istruzione esclude l'utilizzo di istruzioni di dichiarazione e istruzioni con etichetta in questi contesti.The use of embedded_statement rather than statement excludes the use of declaration statements and labeled statements in these contexts. EsempioThe example

void F(bool b) {
    if (b)
        int i = 44;
}

genera un errore in fase di compilazione perché un'istruzione if richiede un embedded_statement anziché un' istruzione per il relativo ramo if.results in a compile-time error because an if statement requires an embedded_statement rather than a statement for its if branch. Se questo codice è stato consentito, la variabile i verrebbe dichiarata, ma non potrebbe mai essere utilizzata.If this code were permitted, then the variable i would be declared, but it could never be used. Si noti, tuttavia, che iinserendo la dichiarazione in un blocco, l'esempio è valido.Note, however, that by placing i's declaration in a block, the example is valid.

Punti finali e raggiungibilitàEnd points and reachability

Ogni istruzione ha un endpoint.Every statement has an end point. In termini intuitivi, il punto finale di un'istruzione è il percorso immediatamente successivo all'istruzione.In intuitive terms, the end point of a statement is the location that immediately follows the statement. Le regole di esecuzione per le istruzioni composite (istruzioni che contengono istruzioni incorporate) specificano l'azione eseguita quando il controllo raggiunge il punto finale di un'istruzione incorporata.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. Ad esempio, quando il controllo raggiunge il punto finale di un'istruzione in un blocco, il controllo viene trasferito all'istruzione successiva nel blocco.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 un'istruzione può essere raggiunta dall'esecuzione, l'istruzione è detta raggiungibile.If a statement can possibly be reached by execution, the statement is said to be reachable. Viceversa, se non è possibile che venga eseguita un'istruzione, l'istruzione è detta non raggiungibile.Conversely, if there is no possibility that a statement will be executed, the statement is said to be unreachable.

Nell'esempioIn the example

void F() {
    Console.WriteLine("reachable");
    goto Label;
    Console.WriteLine("unreachable");
    Label:
    Console.WriteLine("reachable");
}

la seconda chiamata di Console.WriteLine non è raggiungibile perché non è possibile che l'istruzione venga eseguita.the second invocation of Console.WriteLine is unreachable because there is no possibility that the statement will be executed.

Viene segnalato un avviso se il compilatore determina che un'istruzione non è raggiungibile.A warning is reported if the compiler determines that a statement is unreachable. In particolare, non è un errore perché un'istruzione non sia raggiungibile.It is specifically not an error for a statement to be unreachable.

Per determinare se un'istruzione o un endpoint specifico è raggiungibile, il compilatore esegue l'analisi del flusso in base alle regole di raggiungibilità definite per ogni istruzione.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. L'analisi del flusso prende in considerazione i valori delle espressioni costanti (espressioni costanti) che controllano il comportamento delle istruzioni, ma i valori possibili delle espressioni non costanti non vengono considerati.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. In altre parole, per finalità di analisi del flusso di controllo, un'espressione non costante di un determinato tipo viene considerata come un possibile valore di quel 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.

Nell'esempioIn the example

void F() {
    const int i = 1;
    if (i == 2) Console.WriteLine("unreachable");
}

l'espressione booleana dell' if istruzione è un'espressione costante perché entrambi gli == operandi dell'operatore sono costanti.the boolean expression of the if statement is a constant expression because both operands of the == operator are constants. Poiché l'espressione costante viene valutata in fase di compilazione, producendo falseil valore Console.WriteLine , la chiamata viene considerata irraggiungibile.As the constant expression is evaluated at compile-time, producing the value false, the Console.WriteLine invocation is considered unreachable. Tuttavia, se i viene modificato come variabile localeHowever, if i is changed to be a local variable

void F() {
    int i = 1;
    if (i == 2) Console.WriteLine("reachable");
}

la Console.WriteLine chiamata è considerata raggiungibile, anche se, in realtà, non verrà mai eseguita.the Console.WriteLine invocation is considered reachable, even though, in reality, it will never be executed.

Il blocco di un membro di funzione è sempre considerato raggiungibile.The block of a function member is always considered reachable. Se successivamente si valutano le regole di raggiungibilità di ogni istruzione in un blocco, è possibile determinare la raggiungibilità di una determinata istruzione.By successively evaluating the reachability rules of each statement in a block, the reachability of any given statement can be determined.

Nell'esempioIn the example

void F(int x) {
    Console.WriteLine("start");
    if (x < 0) Console.WriteLine("negative");
}

la raggiungibilità della seconda Console.WriteLine viene determinata nel modo seguente:the reachability of the second Console.WriteLine is determined as follows:

  • La prima Console.WriteLine istruzione F di espressione è raggiungibile perché il blocco del metodo è raggiungibile.The first Console.WriteLine expression statement is reachable because the block of the F method is reachable.
  • Il punto finale della prima Console.WriteLine istruzione di espressione è raggiungibile perché tale istruzione è raggiungibile.The end point of the first Console.WriteLine expression statement is reachable because that statement is reachable.
  • L' if istruzione è raggiungibile perché il punto finale della prima Console.WriteLine istruzione di espressione è raggiungibile.The if statement is reachable because the end point of the first Console.WriteLine expression statement is reachable.
  • La seconda Console.WriteLine istruzione if di espressione è raggiungibile perché l'espressione booleana dell'istruzione non ha il valore falsecostante.The second Console.WriteLine expression statement is reachable because the boolean expression of the if statement does not have the constant value false.

Ci sono due situazioni in cui si verifica un errore in fase di compilazione per il raggiungimento del punto finale di un'istruzione:There are two situations in which it is a compile-time error for the end point of a statement to be reachable:

  • Poiché l' switch istruzione non consente a una sezione switch di passare alla sezione switch successiva, si tratta di un errore in fase di compilazione per il punto finale dell'elenco di istruzioni di una sezione di opzioni da raggiungere.Because the switch 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 si verifica questo errore, in genere indica che manca un' break istruzione.If this error occurs, it is typically an indication that a break statement is missing.
  • Si tratta di un errore in fase di compilazione per il punto finale del blocco di un membro di funzione che calcola un valore in modo che sia raggiungibile.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 si verifica questo errore, in genere indica che un' return istruzione è mancante.If this error occurs, it typically is an indication that a return statement is missing.

BlocchiBlocks

Un blocco consente di scrivere più istruzioni nei contesti in cui ne è consentita una sola.A block permits multiple statements to be written in contexts where a single statement is allowed.

block
    : '{' statement_list? '}'
    ;

Un blocco è costituito da un statement_list facoltativo (elenchi di istruzioni) racchiuso tra parentesi graffe.A block consists of an optional statement_list (Statement lists), enclosed in braces. Se l'elenco di istruzioni viene omesso, il blocco viene definito vuoto.If the statement list is omitted, the block is said to be empty.

Un blocco può contenere istruzioni di dichiarazione (istruzioni di dichiarazione).A block may contain declaration statements (Declaration statements). L'ambito di una variabile locale o di una costante dichiarata in un blocco è il blocco.The scope of a local variable or constant declared in a block is the block.

Un blocco viene eseguito come segue:A block is executed as follows:

  • Se il blocco è vuoto, il controllo viene trasferito al punto finale del blocco.If the block is empty, control is transferred to the end point of the block.
  • Se il blocco non è vuoto, il controllo viene trasferito all'elenco delle istruzioni.If the block is not empty, control is transferred to the statement list. Quando e se il controllo raggiunge il punto finale dell'elenco di istruzioni, il controllo viene trasferito al punto finale del blocco.When and if control reaches the end point of the statement list, control is transferred to the end point of the block.

L'elenco di istruzioni di un blocco è raggiungibile se il blocco stesso è raggiungibile.The statement list of a block is reachable if the block itself is reachable.

Il punto finale di un blocco è raggiungibile se il blocco è vuoto o se il punto finale dell'elenco di istruzioni è raggiungibile.The end point of a block is reachable if the block is empty or if the end point of the statement list is reachable.

Un blocco che contiene una o più yield istruzioni (l'istruzione yield) viene definito blocco iteratore.A block that contains one or more yield statements (The yield statement) is called an iterator block. I blocchi iteratori vengono usati per implementare i membri della funzione come iteratori (iteratori).Iterator blocks are used to implement function members as iterators (Iterators). Per i blocchi iteratori vengono applicate alcune restrizioni aggiuntive:Some additional restrictions apply to iterator blocks:

  • Si tratta di un errore in fase di compilazione return perché un'istruzione venga visualizzata in un blocco iteratore (ma yield return sono consentite le istruzioni).It is a compile-time error for a return statement to appear in an iterator block (but yield return statements are permitted).
  • Si tratta di un errore in fase di compilazione per un blocco iteratore che contiene un contesto non sicuro (contesti non sicuri).It is a compile-time error for an iterator block to contain an unsafe context (Unsafe contexts). Un blocco iteratore definisce sempre un contesto sicuro, anche quando la relativa dichiarazione è annidata in un contesto non sicuro.An iterator block always defines a safe context, even when its declaration is nested in an unsafe context.

Elenchi di istruzioniStatement lists

Un elenco di istruzioni è costituito da una o più istruzioni scritte in sequenza.A statement list consists of one or more statements written in sequence. Gli elenchi di istruzioni si verificano in Blocks(blocks) ein switch_blocks (l'istruzione switch).Statement lists occur in blocks (Blocks) and in switch_blocks (The switch statement).

statement_list
    : statement+
    ;

Un elenco di istruzioni viene eseguito trasferendo il controllo alla prima istruzione.A statement list is executed by transferring control to the first statement. Quando e se il controllo raggiunge il punto finale di un'istruzione, il controllo viene trasferito all'istruzione successiva.When and if control reaches the end point of a statement, control is transferred to the next statement. Quando e se il controllo raggiunge il punto finale dell'ultima istruzione, il controllo viene trasferito al punto finale dell'elenco di istruzioni.When and if control reaches the end point of the last statement, control is transferred to the end point of the statement list.

Un'istruzione in un elenco di istruzioni è raggiungibile se si verifica almeno una delle condizioni seguenti:A statement in a statement list is reachable if at least one of the following is true:

  • L'istruzione è la prima istruzione e l'elenco di istruzioni è raggiungibile.The statement is the first statement and the statement list itself is reachable.
  • Il punto finale dell'istruzione precedente è raggiungibile.The end point of the preceding statement is reachable.
  • L'istruzione è un'istruzione con etichetta e l'etichetta fa riferimento a un'istruzione raggiungibile goto .The statement is a labeled statement and the label is referenced by a reachable goto statement.

Il punto finale di un elenco di istruzioni è raggiungibile se il punto finale dell'ultima istruzione nell'elenco è raggiungibile.The end point of a statement list is reachable if the end point of the last statement in the list is reachable.

Istruzione vuotaThe empty statement

Un empty_statement non esegue alcuna operazione.An empty_statement does nothing.

empty_statement
    : ';'
    ;

Quando non sono presenti operazioni da eseguire in un contesto in cui è richiesta un'istruzione, viene utilizzata un'istruzione vuota.An empty statement is used when there are no operations to perform in a context where a statement is required.

L'esecuzione di un'istruzione vuota trasferisce semplicemente il controllo al punto finale dell'istruzione.Execution of an empty statement simply transfers control to the end point of the statement. Pertanto, il punto finale di un'istruzione vuota è raggiungibile se l'istruzione Empty è raggiungibile.Thus, the end point of an empty statement is reachable if the empty statement is reachable.

Quando si scrive un' while istruzione con un corpo null, è possibile utilizzare un'istruzione vuota:An empty statement can be used when writing a while statement with a null body:

bool ProcessMessage() {...}

void ProcessMessages() {
    while (ProcessMessage())
        ;
}

Inoltre, è possibile utilizzare un'istruzione vuota per dichiarare un'etichetta immediatamente prima della chiusura}di un blocco: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: ;
}

Istruzioni con etichettaLabeled statements

Un labeled_statement consente a un'istruzione di essere preceduta da un'etichetta.A labeled_statement permits a statement to be prefixed by a label. Le istruzioni con etichetta sono consentite in blocchi, ma non sono consentite come istruzioni incorporate.Labeled statements are permitted in blocks, but are not permitted as embedded statements.

labeled_statement
    : identifier ':' statement
    ;

Un'istruzione con etichetta dichiara un'etichetta con il nome specificato dall' identificatore.A labeled statement declares a label with the name given by the identifier. L'ambito di un'etichetta è l'intero blocco in cui è dichiarata l'etichetta, inclusi tutti i blocchi annidati.The scope of a label is the whole block in which the label is declared, including any nested blocks. Si tratta di un errore in fase di compilazione per due etichette con lo stesso nome con ambiti sovrapposti.It is a compile-time error for two labels with the same name to have overlapping scopes.

È possibile fare riferimento a un'etichetta goto dalle istruzioni (istruzione goto) nell'ambito dell'etichetta.A label can be referenced from goto statements (The goto statement) within the scope of the label. Ciò significa che goto le istruzioni possono trasferire il controllo all'interno di blocchi e blocchi, ma mai in blocchi.This means that goto statements can transfer control within blocks and out of blocks, but never into blocks.

Le etichette hanno uno spazio di dichiarazione e non interferiscono con altri identificatori.Labels have their own declaration space and do not interfere with other identifiers. EsempioThe example

int F(int x) {
    if (x >= 0) goto x;
    x = -x;
    x: return x;
}

è valido e usa il nome x sia come parametro che come etichetta.is valid and uses the name x as both a parameter and a label.

L'esecuzione di un'istruzione con etichetta corrisponde esattamente all'esecuzione dell'istruzione che segue l'etichetta.Execution of a labeled statement corresponds exactly to execution of the statement following the label.

Oltre alla raggiungibilità fornita da un normale flusso di controllo, un'istruzione con etichetta è raggiungibile se un' goto istruzione raggiungibile fa riferimento a tale etichetta.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. Eccezione Se un' goto istruzione si trova all' try interno di un finally oggetto che include un blocco trye l'istruzione con etichetta è esterna a e il punto finale finally del blocco non è raggiungibile, l'istruzione con etichetta non è raggiungibile da Questa goto istruzione).(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.)

Istruzioni di dichiarazioneDeclaration statements

Un declaration_statement dichiara una variabile o una costante locale.A declaration_statement declares a local variable or constant. Le istruzioni di dichiarazione sono consentite in blocchi, ma non sono consentite come istruzioni incorporate.Declaration statements are permitted in blocks, but are not permitted as embedded statements.

declaration_statement
    : local_variable_declaration ';'
    | local_constant_declaration ';'
    ;

Dichiarazioni di variabili localiLocal variable declarations

Un local_variable_declaration dichiara una o più variabili locali.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
    ;

Il local_variable_type di un local_variable_declaration specifica direttamente il tipo delle variabili introdotte dalla dichiarazione o indica con l'identificatore var che il tipo deve essere dedotto in base a un inizializzatore.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. Il tipo è seguito da un elenco di local_variable_declarator, ognuno dei quali introduce una nuova variabile.The type is followed by a list of local_variable_declarators, each of which introduces a new variable. Un local_variable_declarator è costituito da un identificatore che denomina la variabile, seguito facoltativamente da un token "=" e da un local_variable_initializer che fornisce il valore iniziale della variabile.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.

Nel contesto di una dichiarazione di variabile locale, l'identificatore var funge daparola chiave contestuale (Keywords). Quando local_variable_type viene specificato come var e nessun tipo denominato var è nell'ambito, la dichiarazione è una dichiarazione di variabile locale tipizzata in modo implicito, il cui tipo viene dedotto dal tipo dell'espressione dell'inizializzatore associato.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. Le dichiarazioni di variabili locali tipizzate in modo implicito sono soggette alle restrizioni seguenti:Implicitly typed local variable declarations are subject to the following restrictions:

  • Local_variable_declaration non può includere più local_variable_declarator.The local_variable_declaration cannot include multiple local_variable_declarators.
  • Local_variable_declarator deve includere un local_variable_initializer.The local_variable_declarator must include a local_variable_initializer.
  • Local_variable_initializer deve essere un' espressione.The local_variable_initializer must be an expression.
  • L' espressione dell'inizializzatore deve avere un tipo in fase di compilazione.The initializer expression must have a compile-time type.
  • L' espressione dell'inizializzatore non può fare riferimento alla variabile dichiarata stessaThe initializer expression cannot refer to the declared variable itself

Di seguito sono riportati alcuni esempi di dichiarazioni di variabili locali non corrette tipizzate in modo implicito: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

Il valore di una variabile locale viene ottenuto in un'espressione usando un simple_name (nomi semplici) e il valore di una variabile locale viene modificato usando un' assegnazione (operatori di assegnazione).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). Una variabile locale deve essere assegnata definitivamente (assegnazione definita) in ogni posizione in cui viene ottenuto il relativo valore.A local variable must be definitely assigned (Definite assignment) at each location where its value is obtained.

L'ambito di una variabile locale dichiarata in un local_variable_declaration è il blocco in cui si verifica la dichiarazione.The scope of a local variable declared in a local_variable_declaration is the block in which the declaration occurs. Si tratta di un errore per fare riferimento a una variabile locale in una posizione testuale che precede local_variable_declarator della variabile locale.It is an error to refer to a local variable in a textual position that precedes the local_variable_declarator of the local variable. Nell'ambito di una variabile locale, si tratta di un errore in fase di compilazione per dichiarare un'altra variabile o costante locale con lo stesso 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.

Una dichiarazione di variabile locale che dichiara più variabili è equivalente a più dichiarazioni di variabili singole con lo stesso tipo.A local variable declaration that declares multiple variables is equivalent to multiple declarations of single variables with the same type. Inoltre, un inizializzatore di variabile in una dichiarazione di variabile locale corrisponde esattamente a un'istruzione di assegnazione inserita immediatamente dopo la dichiarazione.Furthermore, a variable initializer in a local variable declaration corresponds exactly to an assignment statement that is inserted immediately after the declaration.

EsempioThe example

void F() {
    int x = 1, y, z = x * 2;
}

corrisponde esattamente acorresponds exactly to

void F() {
    int x; x = 1;
    int y;
    int z; z = x * 2;
}

In una dichiarazione di variabile locale tipizzata in modo implicito, il tipo della variabile locale dichiarata viene considerato uguale al tipo dell'espressione utilizzata per inizializzare la variabile.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. Esempio: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>();

Le dichiarazioni di variabili locali tipizzate in modo implicito sopra sono esattamente equivalenti alle dichiarazioni tipizzate in modo esplicito seguenti: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>();

Dichiarazioni di costanti localiLocal constant declarations

Un local_constant_declaration dichiara una o più costanti locali.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
    ;

Il tipo di local_constant_declaration specifica il tipo delle costanti introdotte dalla dichiarazione.The type of a local_constant_declaration specifies the type of the constants introduced by the declaration. Il tipo è seguito da un elenco di constant_declarator, ognuno dei quali introduce una nuova costante.The type is followed by a list of constant_declarators, each of which introduces a new constant. Un constant_declarator è costituito da un identificatore che assegna un nome alla costante, seguito da un token "=", seguito da un constant_expression (espressioni costanti) che fornisce il valore della costante.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.

Il tipo e il constant_expression di una dichiarazione di costante locale devono rispettare le stesse regole di una dichiarazione di membro costante (costanti).The type and constant_expression of a local constant declaration must follow the same rules as those of a constant member declaration (Constants).

Il valore di una costante locale viene ottenuto in un'espressione usando un simple_name (nomi semplici).The value of a local constant is obtained in an expression using a simple_name (Simple names).

L'ambito di una costante locale è il blocco in cui si verifica la dichiarazione.The scope of a local constant is the block in which the declaration occurs. Si tratta di un errore per fare riferimento a una costante locale in una posizione testuale che precede il relativo constant_declarator.It is an error to refer to a local constant in a textual position that precedes its constant_declarator. Nell'ambito di una costante locale, si tratta di un errore in fase di compilazione per dichiarare un'altra variabile o costante locale con lo stesso 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.

Una dichiarazione di costante locale che dichiara più costanti è equivalente a più dichiarazioni di costanti singole con lo stesso tipo.A local constant declaration that declares multiple constants is equivalent to multiple declarations of single constants with the same type.

Istruzioni di espressioneExpression statements

Un expression_statement valuta un'espressione specificata.An expression_statement evaluates a given expression. Il valore calcolato dall'espressione, se presente, viene ignorato.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
    ;

Non tutte le espressioni sono consentite come istruzioni.Not all expressions are permitted as statements. In particolare, x + y le espressioni come e x == 1 che calcolano semplicemente un valore (che verrà rimosso) non sono consentite come istruzioni.In particular, expressions such as x + y and x == 1 that merely compute a value (which will be discarded), are not permitted as statements.

L'esecuzione di un expression_statement valuta l'espressione contenuta e quindi trasferisce il controllo al punto finale di expression_statement.Execution of an expression_statement evaluates the contained expression and then transfers control to the end point of the expression_statement. Il punto finale di un expression_statement è raggiungibile se il expression_statement è raggiungibile.The end point of an expression_statement is reachable if that expression_statement is reachable.

Istruzioni di selezioneSelection statements

Istruzioni di selezione consente di selezionare una delle diverse istruzioni per l'esecuzione in base al valore di un'espressione.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
    ;

Istruzione ifThe if statement

L' if istruzione seleziona un'istruzione per l'esecuzione in base al valore di un'espressione booleana.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
    ;

Una else parte è associata al valore precedente if lessicalmente più vicino consentito dalla sintassi.An else part is associated with the lexically nearest preceding if that is allowed by the syntax. Quindi, un' if istruzione nel formatoThus, an if statement of the form

if (x) if (y) F(); else G();

equivale ais equivalent to

if (x) {
    if (y) {
        F();
    }
    else {
        G();
    }
}

Un' if istruzione viene eseguita come indicato di seguito:An if statement is executed as follows:

  • Viene valutato Boolean_expression (espressioni booleane).The boolean_expression (Boolean expressions) is evaluated.
  • Se l'espressione booleana restituisce true, il controllo viene trasferito alla prima istruzione incorporata.If the boolean expression yields true, control is transferred to the first embedded statement. Quando e se il controllo raggiunge il punto finale di tale istruzione, il controllo viene trasferito al punto finale dell' if istruzione.When and if control reaches the end point of that statement, control is transferred to the end point of the if statement.
  • Se l'espressione booleana restituisce false e se è else presente una parte, il controllo viene trasferito alla seconda istruzione incorporata.If the boolean expression yields false and if an else part is present, control is transferred to the second embedded statement. Quando e se il controllo raggiunge il punto finale di tale istruzione, il controllo viene trasferito al punto finale dell' if istruzione.When and if control reaches the end point of that statement, control is transferred to the end point of the if statement.
  • Se l'espressione booleana restituisce false e se una else parte non è presente, il controllo viene trasferito al punto finale dell' if istruzione.If the boolean expression yields false and if an else part is not present, control is transferred to the end point of the if statement.

La prima istruzione incorporata di if un'istruzione è raggiungibile se l' if istruzione è raggiungibile e l'espressione booleana non ha il valore falsecostante.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.

La seconda istruzione incorporata di if un'istruzione, se presente, è raggiungibile se l' if istruzione è raggiungibile e l'espressione booleana non ha il valore truecostante.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.

Il punto finale di un' if istruzione è raggiungibile se il punto finale di almeno una delle relative istruzioni incorporate è raggiungibile.The end point of an if statement is reachable if the end point of at least one of its embedded statements is reachable. Inoltre, il punto if finale di un'istruzione senza else parte è raggiungibile se l' if istruzione è raggiungibile e l'espressione booleana non ha il valore truecostante.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.

Istruzione switchThe switch statement

L'istruzione switch seleziona per l'esecuzione di un elenco di istruzioni con un'etichetta switch associata che corrisponde al valore dell'espressione 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' ':'
    ;

Un switch_Statement è costituito dalla parola chiave switch, seguita da un'espressione racchiusa tra parentesi (denominata espressione switch), seguita da un switch_block.A switch_statement consists of the keyword switch, followed by a parenthesized expression (called the switch expression), followed by a switch_block. Switch_block è costituito da zero o più switch_section, racchiusi tra parentesi graffe.The switch_block consists of zero or more switch_sections, enclosed in braces. Ogni switch_section è costituito da uno o più switch_label, seguiti da un statement_list (elenchi di istruzioni).Each switch_section consists of one or more switch_labels followed by a statement_list (Statement lists).

Il tipo di regola di un' switch istruzione viene stabilito dall'espressione switch.The governing type of a switch statement is established by the switch expression.

  • Se il tipo dell'espressione switch è sbyte, byte, short, ushort, int, uint, long, ulong, bool, char, 0 o un enum_typeoppure se è il tipo nullable corrispondente a uno di questi tipi , ovvero il tipo di regola dell'istruzione 2.If the type of the switch expression is sbyte, 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 the switch statement.
  • In caso contrario, è necessario che esista esattamente una conversione implicita definita dall'utente (conversioni definite dall'utente) dal tipo dell'espressione switch a uno dei seguenti tipi di regola: sbyte, byte, short, ushort , int, uint, ,long ,char,o, un tipo nullable corrispondente a uno di questi tipi. ulong stringOtherwise, 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.
  • In caso contrario, se non esiste alcuna conversione implicita o se è presente più di una conversione implicita, si verifica un errore in fase di compilazione.Otherwise, if no such implicit conversion exists, or if more than one such implicit conversion exists, a compile-time error occurs.

L'espressione costante di ogni case etichetta deve indicare un valore convertibile in modo implicito (conversioni implicite) nel tipo di regola dell' switch istruzione.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. Si verifica un errore in fase di compilazione se due case o più etichette nella switch stessa istruzione specificano lo stesso valore costante.A compile-time error occurs if two or more case labels in the same switch statement specify the same constant value.

In un'istruzione switch può essere default presente al massimo un'etichetta.There can be at most one default label in a switch statement.

Un' switch istruzione viene eseguita come indicato di seguito:A switch statement is executed as follows:

  • L'espressione switch viene valutata e convertita nel tipo di regola.The switch expression is evaluated and converted to the governing type.
  • Se una delle costanti specificate in un' case etichetta nella stessa switch istruzione è uguale al valore dell'espressione switch, il controllo viene trasferito all' case elenco di istruzioni che segue l'etichetta corrispondente.If one of the constants specified in a case label in the same switch statement is equal to the value of the switch expression, control is transferred to the statement list following the matched case label.
  • Se nessuna case delle costanti specificate nelle etichette nella stessa switch istruzione è uguale al valore dell'espressione switch e se è presente un' default etichetta, il controllo default viene trasferito all'elenco di istruzioni che segue etichetta.If none of the constants specified in case labels in the same switch statement is equal to the value of the switch expression, and if a default label is present, control is transferred to the statement list following the default label.
  • Se nessuna case delle costanti specificate nelle etichette nella stessa switch istruzione è uguale al valore dell'espressione switch e se non è presente alcuna default etichetta, il controllo switch viene trasferito al punto finale dell'istruzione.If none of the constants specified in case labels in the same switch statement is equal to the value of the switch expression, and if no default label is present, control is transferred to the end point of the switch statement.

Se il punto finale dell'elenco di istruzioni di una sezione switch è raggiungibile, si verifica un errore in fase di compilazione.If the end point of the statement list of a switch section is reachable, a compile-time error occurs. Questa operazione è nota come regola "No fall through".This is known as the "no fall through" rule. EsempioThe example

switch (i) {
case 0:
    CaseZero();
    break;
case 1:
    CaseOne();
    break;
default:
    CaseOthers();
    break;
}

è valido perché nessuna sezione switch ha un endpoint raggiungibile.is valid because no switch section has a reachable end point. Diversamente da C e C++, l'esecuzione di una sezione switch non è consentita per passare alla sezione switch successiva e l'esempioUnlike 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();
}

genera un errore in fase di compilazione.results in a compile-time error. Quando l'esecuzione di una sezione switch deve essere seguita dall'esecuzione di un'altra sezione switch, è goto case necessario goto default usare un'istruzione o esplicita: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;
}

In un switch_sectionsono consentite più etichette.Multiple labels are permitted in a switch_section. EsempioThe example

switch (i) {
case 0:
    CaseZero();
    break;
case 1:
    CaseOne();
    break;
case 2:
default:
    CaseTwo();
    break;
}

è valido.is valid. L'esempio non viola la regola "No fall through" perché le etichette case 2: e default: fanno parte dello stesso 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.

La regola "No fall through" impedisce una classe comune di bug che si verificano in C++ C break e in caso di omissione accidentale delle istruzioni.The "no fall through" rule prevents a common class of bugs that occur in C and C++ when break statements are accidentally omitted. Inoltre, a causa di questa regola, le sezioni switch di un' switch istruzione possono essere riorganizzate arbitrariamente senza influire sul comportamento dell'istruzione.In addition, because of this rule, the switch sections of a switch statement can be arbitrarily rearranged without affecting the behavior of the statement. Le sezioni dell' switch istruzione precedente, ad esempio, possono essere invertite senza influire sul comportamento dell'istruzione: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;
}

L'elenco di istruzioni di una sezione switch termina in genere breakin goto caseun'istruzione goto default , o, ma qualsiasi costrutto che esegue il rendering del punto finale dell'elenco di istruzioni non raggiungibile è consentito.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. Ad esempio, un' while istruzione controllata dall'espressione true booleana è nota che non raggiunge mai il punto finale.For example, a while statement controlled by the boolean expression true is known to never reach its end point. Analogamente, throw un' return istruzione o trasferisce sempre il controllo altrove e non raggiunge mai il punto finale.Likewise, a throw or return statement always transfers control elsewhere and never reaches its end point. Di conseguenza, l'esempio seguente è valido:Thus, the following example is valid:

switch (i) {
case 0:
    while (true) F();
case 1:
    throw new ArgumentException();
case 2:
    return;
}

Il tipo di regola di un' switch istruzione può essere il tipo string.The governing type of a switch statement may be the type string. Esempio: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;
    }
}

Analogamente agli operatori di uguaglianza di stringa (operatori di uguaglianza switch distringa), l'istruzione fa distinzione tra maiuscole e minuscole e consente di eseguire una determinata case sezione switch solo se la stringa dell'espressione switch corrisponde esattamente a una costante Label.Like 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 il tipo di regola di un' switch istruzione è string, il valore null è consentito come costante di etichetta case.When the governing type of a switch statement is string, the value null is permitted as a case label constant.

Il statement_lists di un switch_block può contenere istruzioni di dichiarazione (istruzioni di dichiarazione).The statement_lists of a switch_block may contain declaration statements (Declaration statements). L'ambito di una variabile locale o di una costante dichiarata in un blocco switch è il blocco switch.The scope of a local variable or constant declared in a switch block is the switch block.

L'elenco di istruzioni di una sezione switch specificata è raggiungibile se l' switch istruzione è raggiungibile e viene soddisfatta almeno una delle condizioni seguenti: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:

  • L'espressione switch è un valore non costante.The switch expression is a non-constant value.
  • L'espressione switch è un valore costante che corrisponde a case un'etichetta nella sezione switch.The switch expression is a constant value that matches a case label in the switch section.
  • L'espressione switch è un valore costante che non corrisponde ad case alcuna etichetta e la sezione switch contiene l' default etichetta.The switch expression is a constant value that doesn't match any case label, and the switch section contains the default label.
  • Un'etichetta switch della sezione switch è a cui fa riferimento un'istruzione goto case o goto default raggiungibile.A switch label of the switch section is referenced by a reachable goto case or goto default statement.

Il punto finale di un' switch istruzione è raggiungibile se si verifica almeno una delle condizioni seguenti:The end point of a switch statement is reachable if at least one of the following is true:

  • L' switch istruzione contiene un'istruzione break raggiungibile che esce dall' switch istruzione.The switch statement contains a reachable break statement that exits the switch statement.
  • L' switch istruzione è raggiungibile, l'espressione switch è un valore non costante e non è presente alcuna default etichetta.The switch statement is reachable, the switch expression is a non-constant value, and no default label is present.
  • L' switch istruzione è raggiungibile, l'espressione switch è un valore costante che non corrisponde ad alcuna case etichetta e non è default presente alcuna etichetta.The switch statement is reachable, the switch expression is a constant value that doesn't match any case label, and no default label is present.

Istruzioni di iterazioneIteration statements

Le istruzioni di iterazione eseguono ripetutamente un'istruzione incorporata.Iteration statements repeatedly execute an embedded statement.

iteration_statement
    : while_statement
    | do_statement
    | for_statement
    | foreach_statement
    ;

Istruzione whileThe while statement

L' while istruzione esegue in modo condizionale un'istruzione incorporata zero o più volte.The while statement conditionally executes an embedded statement zero or more times.

while_statement
    : 'while' '(' boolean_expression ')' embedded_statement
    ;

Un' while istruzione viene eseguita come indicato di seguito:A while statement is executed as follows:

  • Viene valutato Boolean_expression (espressioni booleane).The boolean_expression (Boolean expressions) is evaluated.
  • Se l'espressione booleana restituisce true, il controllo viene trasferito all'istruzione incorporata.If the boolean expression yields true, control is transferred to the embedded statement. Quando e se il controllo raggiunge il punto finale dell'istruzione incorporata (possibilmente dall'esecuzione continue di un'istruzione), il controllo viene trasferito all'inizio while dell'istruzione.When and if control reaches the end point of the embedded statement (possibly from execution of a continue statement), control is transferred to the beginning of the while statement.
  • Se l'espressione booleana restituisce false, il controllo viene trasferito al punto finale while dell'istruzione.If the boolean expression yields false, control is transferred to the end point of the while statement.

All'interno dell'istruzione incorporata while di un'istruzione break , un'istruzione (istruzione break) può essere utilizzata per trasferire il while controllo al punto finale dell'istruzione (in modo che termina l'iterazione dell'istruzione incorporata) e continue è possibile utilizzare l'istruzione (istruzione continue) per trasferire il controllo al punto finale dell'istruzione incorporata, eseguendo così un'altra while iterazione dell'istruzione.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).

L'istruzione incorporata di while un'istruzione è raggiungibile se l' while istruzione è raggiungibile e l'espressione booleana non ha il valore falsecostante.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.

Il punto finale di un' while istruzione è raggiungibile se si verifica almeno una delle condizioni seguenti:The end point of a while statement is reachable if at least one of the following is true:

  • L' while istruzione contiene un'istruzione break raggiungibile che esce dall' while istruzione.The while statement contains a reachable break statement that exits the while statement.
  • L' while istruzione è raggiungibile e l'espressione booleana non ha il valore truecostante.The while statement is reachable and the boolean expression does not have the constant value true.

Istruzione doThe do statement

L' do istruzione esegue in modo condizionale un'istruzione incorporata una o più volte.The do statement conditionally executes an embedded statement one or more times.

do_statement
    : 'do' embedded_statement 'while' '(' boolean_expression ')' ';'
    ;

Un' do istruzione viene eseguita come indicato di seguito:A do statement is executed as follows:

  • Il controllo viene trasferito all'istruzione incorporata.Control is transferred to the embedded statement.
  • Quando e se il controllo raggiunge il punto finale dell'istruzione incorporata (possibilmente dall'esecuzione di un'istruzione continue), viene valutato Boolean_expression (espressioni booleane).When and if control reaches the end point of the embedded statement (possibly from execution of a continue statement), the boolean_expression (Boolean expressions) is evaluated. Se l'espressione booleana restituisce true, il controllo viene trasferito all'inizio do dell'istruzione.If the boolean expression yields true, control is transferred to the beginning of the do statement. In caso contrario, il controllo viene trasferito al punto finale do dell'istruzione.Otherwise, control is transferred to the end point of the do statement.

All'interno dell'istruzione incorporata do di un'istruzione break , un'istruzione (istruzione break) può essere utilizzata per trasferire il do controllo al punto finale dell'istruzione (in modo che termina l'iterazione dell'istruzione incorporata) e continue l'istruzione (istruzione continue) può essere utilizzata per trasferire il controllo al punto finale dell'istruzione incorporata.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.

L'istruzione incorporata di do un'istruzione è raggiungibile se l' do istruzione è raggiungibile.The embedded statement of a do statement is reachable if the do statement is reachable.

Il punto finale di un' do istruzione è raggiungibile se si verifica almeno una delle condizioni seguenti:The end point of a do statement is reachable if at least one of the following is true:

  • L' do istruzione contiene un'istruzione break raggiungibile che esce dall' do istruzione.The do statement contains a reachable break statement that exits the do statement.
  • Il punto finale dell'istruzione incorporata è raggiungibile e l'espressione booleana non ha il valore truecostante.The end point of the embedded statement is reachable and the boolean expression does not have the constant value true.

Istruzione forThe for statement

L' for istruzione valuta una sequenza di espressioni di inizializzazione e quindi, mentre una condizione è true, esegue ripetutamente un'istruzione incorporata e valuta una sequenza di espressioni di iterazione.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)*
    ;

Il valore di for_initializer, se presente, è costituito da un local_variable_declaration (dichiarazioni di variabili locali) o da un elenco di statement_expressions (istruzioni di espressione) separate da virgole.The for_initializer, if present, consists of either a local_variable_declaration (Local variable declarations) or a list of statement_expressions (Expression statements) separated by commas. L'ambito di una variabile locale dichiarata da un for_initializer inizia da local_variable_declarator per la variabile e si estende fino alla fine dell'istruzione incorporata.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. L'ambito include for_condition e for_iterator.The scope includes the for_condition and the for_iterator.

For_condition, se presente, deve essere un Boolean_expression (espressioni booleane).The for_condition, if present, must be a boolean_expression (Boolean expressions).

Il valore di for_iterator, se presente, è costituito da un elenco di statement_expression(istruzioni di espressione) separate da virgole.The for_iterator, if present, consists of a list of statement_expressions (Expression statements) separated by commas.

Un'istruzione for viene eseguita come indicato di seguito:A for statement is executed as follows:

  • Se è presente un for_initializer , gli inizializzatori di variabile o le espressioni di istruzione vengono eseguiti nell'ordine in cui vengono scritti.If a for_initializer is present, the variable initializers or statement expressions are executed in the order they are written. Questo passaggio viene eseguito una sola volta.This step is only performed once.
  • Se è presente un for_condition , viene valutato.If a for_condition is present, it is evaluated.
  • Se for_condition non è presente o se la valutazione restituisce true, il controllo viene trasferito all'istruzione incorporata.If the for_condition is not present or if the evaluation yields true, control is transferred to the embedded statement. Quando e se il controllo raggiunge il punto finale dell'istruzione incorporata (possibilmente dall'esecuzione di un'istruzione continue), le espressioni di for_iterator, se presenti, vengono valutate in sequenza, quindi viene eseguita un'altra iterazione, a partire da valutazione del for_condition nel passaggio precedente.When and if control reaches the end point of the embedded statement (possibly from execution of a continue 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 for_condition è presente e la valutazione restituisce false, il controllo viene trasferito al punto finale dell'istruzione for.If the for_condition is present and the evaluation yields false, control is transferred to the end point of the for statement.

All'interno dell'istruzione incorporata di un'istruzione for, è possibile utilizzare un'istruzione break (istruzione break) per trasferire il controllo al punto finale dell'istruzione for (terminando quindi l'iterazione dell'istruzione incorporata) e un'istruzione continue ( L'istruzione continue) può essere utilizzata per trasferire il controllo al punto finale dell'istruzione incorporata, eseguendo in questo modo for_iterator ed eseguendo un'altra iterazione dell'istruzione for, a partire da 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).

L'istruzione incorporata di for un'istruzione è raggiungibile se si verifica una delle condizioni seguenti:The embedded statement of a for statement is reachable if one of the following is true:

  • L'istruzione for è raggiungibile e non è presente alcun for_condition .The for statement is reachable and no for_condition is present.
  • L'istruzione for è raggiungibile e un for_condition è presente e non ha il valore costante false.The for statement is reachable and a for_condition is present and does not have the constant value false.

Il punto finale di un' for istruzione è raggiungibile se si verifica almeno una delle condizioni seguenti:The end point of a for statement is reachable if at least one of the following is true:

  • L' for istruzione contiene un'istruzione break raggiungibile che esce dall' for istruzione.The for statement contains a reachable break statement that exits the for statement.
  • L'istruzione for è raggiungibile e un for_condition è presente e non ha il valore costante true.The for statement is reachable and a for_condition is present and does not have the constant value true.

Istruzione foreachThe foreach statement

L' foreach istruzione enumera gli elementi di una raccolta, eseguendo un'istruzione incorporata per ogni elemento della raccolta.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
    ;

Il tipo e l' identificatore di foreach un'istruzione dichiarano la variabile di iterazione dell'istruzione.The type and identifier of a foreach statement declare the iteration variable of the statement. Se l'identificatore var viene specificato come local_variable_typee nessun tipo denominato var è nell'ambito, la variabile di iterazione è una variabile di iterazione tipizzata in modo implicitoe il tipo viene considerato come il tipo di elemento del foreach , come specificato di seguito.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. La variabile di iterazione corrisponde a una variabile locale di sola lettura con un ambito che si estende sull'istruzione incorporata.The iteration variable corresponds to a read-only local variable with a scope that extends over the embedded statement. Durante l'esecuzione di foreach un'istruzione, la variabile di iterazione rappresenta l'elemento della raccolta per il quale è attualmente in corso l'esecuzione di un'iterazione.During execution of a foreach statement, the iteration variable represents the collection element for which an iteration is currently being performed. Si verifica un errore in fase di compilazione se l'istruzione incorporata tenta di modificare la variabile di iterazione ++ ( -- tramite assegnazione o gli operatori e) o di ref passare out la variabile di iterazione come parametro o.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.

Nell'esempio seguente, per brevità IEnumerable, IEnumerator IEnumerable<T> , e IEnumerator<T> si riferiscono ai tipi corrispondenti negli spazi System.Collections dei System.Collections.Genericnomi e.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.

L'elaborazione in fase di compilazione di un'istruzione foreach determina innanzitutto il tipo di raccolta, il tipo di enumeratore e il tipo di elemento dell'espressione.The compile-time processing of a foreach statement first determines the collection type, enumerator type and element type of the expression. Questa determinazione procede come segue:This determination proceeds as follows:

  • Se il tipo X di espressione è un tipo di matrice, esiste una X IEnumerable conversione implicita del riferimento da all'interfaccia ( System.Array poiché implementa questa interfaccia).If the type X of expression is an array type then there is an implicit reference conversion from X to the IEnumerable interface (since System.Array implements this interface). Il tipo di raccolta è IEnumerable l'interfaccia, il tipo di enumeratore è IEnumerator l'interfaccia e il tipo di elemento è il tipo di Xelemento del tipo di matrice.The collection type is the IEnumerable interface, the enumerator type is the IEnumerator interface and the element type is the element type of the array type X.

  • Se il tipo X di espressione è dynamic , esiste IEnumerable una conversione implicita dall' espressione all'interfaccia (conversioni dinamiche implicite).If the type X of expression is dynamic then there is an implicit conversion from expression to the IEnumerable interface (Implicit dynamic conversions). Il tipo di raccolta è IEnumerable l'interfaccia e il tipo di enumeratore è l' IEnumerator interfaccia.The collection type is the IEnumerable interface and the enumerator type is the IEnumerator interface. Se l'identificatore var viene specificato come local_variable_type , il tipo di elemento sarà dynamic, in caso contrario sarà object.If the var identifier is given as the local_variable_type then the element type is dynamic, otherwise it is object.

  • In caso contrario, determinare se X il tipo dispone GetEnumerator di un metodo appropriato:Otherwise, determine whether the type X has an appropriate GetEnumerator method:

    • Eseguire la ricerca di membri sul X tipo con GetEnumerator identificatore e nessun argomento di tipo.Perform member lookup on the type X with identifier GetEnumerator and no type arguments. Se la ricerca dei membri non produce una corrispondenza o produce un'ambiguità o produce una corrispondenza che non è un gruppo di metodi, verificare la presenza di un'interfaccia enumerabile come descritto di seguito.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. Si consiglia di emettere un avviso se la ricerca di membri produce qualsiasi elemento tranne un gruppo di metodi o nessuna corrispondenza.It is recommended that a warning be issued if member lookup produces anything except a method group or no match.
    • Eseguire la risoluzione dell'overload usando il gruppo di metodi risultante e un elenco di argomenti vuoto.Perform overload resolution using the resulting method group and an empty argument list. Se la risoluzione dell'overload non produce metodi applicabili, comporta un'ambiguità o produce un unico metodo migliore, ma tale metodo è statico o non pubblico, verificare la presenza di un'interfaccia enumerabile come descritto di seguito.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. Si consiglia di emettere un avviso se la risoluzione dell'overload produce qualsiasi elemento tranne un metodo di istanza pubblica non ambiguo o senza metodi applicabili.It is recommended that a warning be issued if overload resolution produces anything except an unambiguous public instance method or no applicable methods.
    • Se il tipo E restituito GetEnumerator del metodo non è una classe, uno struct o un tipo di interfaccia, viene generato un errore e non vengono eseguiti altri passaggi.If the return type E of the GetEnumerator method is not a class, struct or interface type, an error is produced and no further steps are taken.
    • La ricerca del membro viene E eseguita con l' Current identificatore e nessun argomento di tipo.Member lookup is performed on E with the identifier Current and no type arguments. Se la ricerca dei membri non produce corrispondenze, il risultato è un errore o il risultato è qualsiasi eccezione, ad eccezione di una proprietà di istanza pubblica che consente la lettura, viene generato un errore e non vengono eseguiti altri passaggi.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.
    • La ricerca del membro viene E eseguita con l' MoveNext identificatore e nessun argomento di tipo.Member lookup is performed on E with the identifier MoveNext and no type arguments. Se la ricerca dei membri non produce corrispondenze, il risultato è un errore o il risultato è qualsiasi eccezione a un gruppo di metodi, viene generato un errore e non vengono eseguiti altri passaggi.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.
    • La risoluzione dell'overload viene eseguita sul gruppo di metodi con un elenco di argomenti vuoto.Overload resolution is performed on the method group with an empty argument list. Se la risoluzione dell'overload non produce metodi applicabili, comporta un'ambiguità o produce un unico metodo migliore, ma tale metodo è statico o non pubblico oppure il tipo restituito non boollo è, viene generato un errore e non vengono eseguiti altri passaggi.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 not bool, an error is produced and no further steps are taken.
    • Il tipo di raccolta Xè, il tipo di E enumeratore è Current e il tipo di elemento è il tipo della proprietà.The collection type is X, the enumerator type is E, and the element type is the type of the Current property.
  • In caso contrario, verificare la presenza di un'interfaccia enumerabile:Otherwise, check for an enumerable interface:

    • Se tra tutti i tipi Ti per i quali esiste una conversione implicita X da IEnumerable<Ti>a, esiste un tipo T univoco che T non dynamic è e per tutti gli altri Ti è presente un IEnumerable<T> la conversione implicita da a, quindi il tipo di raccolta è l' IEnumerable<T>interfaccia, il tipo di IEnumerator<T> IEnumerable<Ti>enumeratore è l'interfaccia e il tipo di elemento è T.If among all the types Ti for which there is an implicit conversion from X to IEnumerable<Ti>, there is a unique type T such that T is not dynamic and for all the other Ti there is an implicit conversion from IEnumerable<T> to IEnumerable<Ti>, then the collection type is the interface IEnumerable<T>, the enumerator type is the interface IEnumerator<T>, and the element type is T.
    • In caso contrario, se è presente più di un Ttipo di questo tipo, viene generato un errore e non vengono eseguiti altri passaggi.Otherwise, if there is more than one such type T, then an error is produced and no further steps are taken.
    • In caso contrario, se esiste una X conversione implicita da System.Collections.IEnumerable all'interfaccia, il tipo di raccolta è questa interfaccia, il tipo di enumeratore è l'interfaccia System.Collections.IEnumeratore il tipo di elemento è object.Otherwise, if there is an implicit conversion from X to the System.Collections.IEnumerable interface, then the collection type is this interface, the enumerator type is the interface System.Collections.IEnumerator, and the element type is object.
    • In caso contrario, viene generato un errore e non vengono eseguiti altri passaggi.Otherwise, an error is produced and no further steps are taken.

I passaggi precedenti, se riusciti, producono in modo non ambiguo un Ctipo di raccolta E , un tipo Tdi enumeratore e un tipo di elemento.The above steps, if successful, unambiguously produce a collection type C, enumerator type E and element type T. Istruzione foreach nel formatoA foreach statement of the form

foreach (V v in x) embedded_statement

viene quindi espanso in:is then expanded to:

{
    E e = ((C)(x)).GetEnumerator();
    try {
        while (e.MoveNext()) {
            V v = (V)(T)e.Current;
            embedded_statement
        }
    }
    finally {
        ... // Dispose e
    }
}

La variabile e non è visibile o accessibile all'espressione x o all'istruzione incorporata o a qualsiasi altro codice sorgente del programma.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. La variabile v è di sola lettura nell'istruzione incorporata.The variable v is read-only in the embedded statement. Se non è presente una conversione esplicita (conversioni esplicite) da T (il tipo di elemento) a V ( local_variable_type nell'istruzione foreach), viene generato un errore e non vengono eseguiti altri passaggi.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 ha il valore null, viene System.NullReferenceException generata un'eccezione in fase di esecuzione.If x has the value null, a System.NullReferenceException is thrown at run-time.

Un'implementazione può implementare una determinata istruzione foreach in modo diverso, ad esempio per motivi di prestazioni, purché il comportamento sia coerente con l'espansione precedente.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.

La posizione di v all'interno del ciclo while è importante per il modo in cui viene acquisita da qualsiasi funzione anonima che si verifica in 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.

Esempio: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 è stato dichiarato all'esterno del ciclo while, verrebbe condiviso tra tutte le iterazioni e il relativo valore dopo il ciclo for sarebbe il valore finale, 13, che corrisponde alla chiamata di f stampa.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. Al contrario, poiché ogni iterazione dispone di vuna propria variabile, quella f acquisita dalla prima iterazione continuerà a contenere 7il valore, che è quello che verrà stampato.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. (Nota: le versioni precedenti C# di v sono state dichiarate all'esterno del ciclo while).(Note: earlier versions of C# declared v outside of the while loop.)

Il corpo del blocco finally viene costruito in base ai passaggi seguenti:The body of the finally block is constructed according to the following steps:

  • Se esiste una conversione implicita da E System.IDisposable all'interfaccia,If there is an implicit conversion from E to the System.IDisposable interface, then

    • Se E è un tipo di valore non nullable, la clausola finally viene espansa nell'equivalente semantico di:If E is a non-nullable value type then the finally clause is expanded to the semantic equivalent of:

      finally {
          ((System.IDisposable)e).Dispose();
      }
      
    • In caso contrario, la clausola finally viene espansa all'equivalente semantico di:Otherwise the finally clause is expanded to the semantic equivalent of:

      finally {
          if (e != null) ((System.IDisposable)e).Dispose();
      }
      

    ad eccezione del E fatto che se è un tipo di valore o un parametro di tipo di cui è stata creata un'istanza e a System.IDisposable un tipo di valore, il cast di a non comporterà la conversione boxing.except that if E is a value type, or a type parameter instantiated to a value type, then the cast of e to System.IDisposable will not cause boxing to occur.

  • In caso contrario E , se è un tipo sealed, la clausola finally viene espansa in un blocco vuoto:Otherwise, if E is a sealed type, the finally clause is expanded to an empty block:

    finally {
    }
    
  • In caso contrario, la clausola finally viene espansa in:Otherwise, the finally clause is expanded to:

    finally {
        System.IDisposable d = e as System.IDisposable;
        if (d != null) d.Dispose();
    }
    

    La variabile d locale non è visibile o accessibile a qualsiasi codice utente.The local variable d is not visible to or accessible to any user code. In particolare, non è in conflitto con altre variabili il cui ambito include il blocco finally.In particular, it does not conflict with any other variable whose scope includes the finally block.

L'ordine in cui foreach attraversa gli elementi di una matrice è il seguente: Per gli elementi delle matrici unidimensionali viene attraversato l'ordine di indice crescente, iniziando con 0 index e terminando Length - 1con index.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. Per le matrici multidimensionali, gli elementi vengono attraversati in modo che gli indici della dimensione più a destra vengano aumentati per primi, quindi la dimensione sinistra successiva e così via verso sinistra.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.

Nell'esempio seguente viene stampato ogni valore in una matrice bidimensionale, nell'ordine degli elementi: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();
    }
}

L'output prodotto è il seguente:The output produced is as follows:

1.2 2.3 3.4 4.5 5.6 6.7 7.8 8.9

Nell'esempioIn the example

int[] numbers = { 1, 3, 5, 7, 9 };
foreach (var n in numbers) Console.WriteLine(n);

il tipo di n viene dedotto intcome, il tipo di elemento di numbers.the type of n is inferred to be int, the element type of numbers.

Istruzioni di saltoJump statements

Istruzioni Jump che trasferiscono il controllo in modo non condizionale.Jump statements unconditionally transfer control.

jump_statement
    : break_statement
    | continue_statement
    | goto_statement
    | return_statement
    | throw_statement
    ;

Il percorso in cui un'istruzione Jump trasferisce il controllo è chiamato la destinazione dell'istruzione Jump.The location to which a jump statement transfers control is called the target of the jump statement.

Quando un'istruzione Jump si verifica all'interno di un blocco e la destinazione dell'istruzione Jump è esterna a tale blocco, viene detto che l'istruzione Jump esce dal blocco.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. Mentre un'istruzione Jump può trasferire il controllo da un blocco, non può mai trasferire il controllo in un blocco.While a jump statement may transfer control out of a block, it can never transfer control into a block.

L'esecuzione di istruzioni di salto è complessa dalla presenza di try istruzioni che interessano.Execution of jump statements is complicated by the presence of intervening try statements. In assenza di tali try istruzioni, un'istruzione Jump trasferisce in modo incondizionato il controllo dall'istruzione Jump alla relativa destinazione.In the absence of such try statements, a jump statement unconditionally transfers control from the jump statement to its target. In presenza di tali try istruzioni, l'esecuzione è più complessa.In the presence of such intervening try statements, execution is more complex. Se l'istruzione Jump esce da uno o più try blocchi con blocchi finally associati, il controllo finally viene inizialmente trasferito al blocco dell'istruzione più try 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 il controllo raggiunge il punto finale di finally un blocco, il finally controllo viene trasferito al blocco della successiva istruzione di try inclusione.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. Questo processo viene ripetuto fino a finally quando non vengono eseguiti i try blocchi di tutte le istruzioni coinvolte.This process is repeated until the finally blocks of all intervening try statements have been executed.

Nell'esempioIn 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");
    }
}

i finally blocchi associati a due try istruzioni vengono eseguiti prima che il controllo venga trasferito alla destinazione dell'istruzione Jump.the finally blocks associated with two try statements are executed before control is transferred to the target of the jump statement.

L'output prodotto è il seguente:The output produced is as follows:

Before break
Innermost finally block
Outermost finally block
After break

Istruzione breakThe break statement

L' break istruzione esce dall'istruzione di inclusione switch, while do for,, o foreach più vicina.The break statement exits the nearest enclosing switch, while, do, for, or foreach statement.

break_statement
    : 'break' ';'
    ;

La destinazione di un' break istruzione è il punto finale dell'istruzione di inclusione switchpiù whilevicina do, for,, foreach o.The target of a break statement is the end point of the nearest enclosing switch, while, do, for, or foreach statement. Se un' break istruzione non è racchiusa tra switchun' whileistruzione do, for,, foreach o, si verifica un errore in fase di compilazione.If a break statement is not enclosed by a switch, while, do, for, or foreach statement, a compile-time error occurs.

Quando più switchistruzioni while break ,, ,for oforeach sono annidate all'interno di un'altra, un'istruzione si applica solo all'istruzione più interna. doWhen multiple switch, while, do, for, or foreach statements are nested within each other, a break statement applies only to the innermost statement. Per trasferire il controllo tra più livelli di nidificazione goto , è necessario utilizzare un'istruzione (istruzione goto).To transfer control across multiple nesting levels, a goto statement (The goto statement) must be used.

Un' break istruzione non può uscire finally da un blocco (istruzione try).A break statement cannot exit a finally block (The try statement). Quando un' break istruzione si verifica all' finally interno di un blocco break , la destinazione dell'istruzione deve trovarsi finally all'interno dello stesso blocco; in caso contrario, si verifica un errore in fase di compilazione.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.

Un' break istruzione viene eseguita come indicato di seguito:A break statement is executed as follows:

  • Se l' break istruzione esce da uno o più try blocchi con finally blocchi finally associati, il controllo viene inizialmente trasferito al blocco dell'istruzione più try interna.If the break 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 il controllo raggiunge il punto finale di finally un blocco, il finally controllo viene trasferito al blocco della successiva istruzione di try inclusione.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. Questo processo viene ripetuto fino a finally quando non vengono eseguiti i try blocchi di tutte le istruzioni coinvolte.This process is repeated until the finally blocks of all intervening try statements have been executed.
  • Il controllo viene trasferito alla destinazione dell' break istruzione.Control is transferred to the target of the break statement.

Poiché un' break istruzione trasferisce in modo incondizionato il controllo altrove, il break punto finale di un'istruzione non è mai raggiungibile.Because a break statement unconditionally transfers control elsewhere, the end point of a break statement is never reachable.

Istruzione continueThe continue statement

L' continue istruzione avvia una nuova iterazione dell'istruzione di inclusione do while, for, o foreach più vicina.The continue statement starts a new iteration of the nearest enclosing while, do, for, or foreach statement.

continue_statement
    : 'continue' ';'
    ;

La destinazione di un' continue istruzione è il punto finale dell'istruzione incorporata dell'istruzione, do, foro while foreach di inclusione più vicina.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 un' continue istruzione non è racchiusa tra whileun' doistruzione for,, foreach o, si verifica un errore in fase di compilazione.If a continue statement is not enclosed by a while, do, for, or foreach statement, a compile-time error occurs.

Quando più whileistruzioni do continue ,, o foreach sono annidate all'interno di un'altra, un'istruzione si applica solo all'istruzione più interna. forWhen multiple while, do, for, or foreach statements are nested within each other, a continue statement applies only to the innermost statement. Per trasferire il controllo tra più livelli di nidificazione goto , è necessario utilizzare un'istruzione (istruzione goto).To transfer control across multiple nesting levels, a goto statement (The goto statement) must be used.

Un' continue istruzione non può uscire finally da un blocco (istruzione try).A continue statement cannot exit a finally block (The try statement). Quando un' continue istruzione si verifica all' finally interno di un blocco continue , la destinazione dell'istruzione deve trovarsi finally all'interno dello stesso blocco; in caso contrario, si verifica un errore in fase di compilazione.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.

Un' continue istruzione viene eseguita come indicato di seguito:A continue statement is executed as follows:

  • Se l' continue istruzione esce da uno o più try blocchi con finally blocchi finally associati, il controllo viene inizialmente trasferito al blocco dell'istruzione più try interna.If the continue 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 il controllo raggiunge il punto finale di finally un blocco, il finally controllo viene trasferito al blocco della successiva istruzione di try inclusione.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. Questo processo viene ripetuto fino a finally quando non vengono eseguiti i try blocchi di tutte le istruzioni coinvolte.This process is repeated until the finally blocks of all intervening try statements have been executed.
  • Il controllo viene trasferito alla destinazione dell' continue istruzione.Control is transferred to the target of the continue statement.

Poiché un' continue istruzione trasferisce in modo incondizionato il controllo altrove, il continue punto finale di un'istruzione non è mai raggiungibile.Because a continue statement unconditionally transfers control elsewhere, the end point of a continue statement is never reachable.

Istruzione GoToThe goto statement

L' goto istruzione trasferisce il controllo a un'istruzione contrassegnata da un'etichetta.The goto statement transfers control to a statement that is marked by a label.

goto_statement
    : 'goto' identifier ';'
    | 'goto' 'case' constant_expression ';'
    | 'goto' 'default' ';'
    ;

La destinazione di un' goto istruzione Identifier è l'istruzione con etichetta con l'etichetta specificata.The target of a goto identifier statement is the labeled statement with the given label. Se un'etichetta con il nome specificato non esiste nel membro della funzione corrente o se l' goto istruzione non è inclusa nell'ambito dell'etichetta, si verifica un errore in fase di compilazione.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. Questa regola consente di utilizzare un' goto istruzione per trasferire il controllo da un ambito annidato, ma non da un ambito annidato.This rule permits the use of a goto statement to transfer control out of a nested scope, but not into a nested scope. Nell'esempioIn 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);
        }
    }
}

viene goto utilizzata un'istruzione per trasferire il controllo da un ambito annidato.a goto statement is used to transfer control out of a nested scope.

La destinazione di un' goto case istruzione è l'elenco di istruzioni nell'istruzione di inclusione switch immediata (istruzione switch), che contiene un' case etichetta con il valore costante specificato.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 l'istruzione goto case non è racchiusa tra un'istruzione switch, se constant_expression non è implicitamente convertibile (conversioni implicite) nel tipo di regola dell'istruzione switch di inclusione più vicina o se il valore di inclusione più vicino l'istruzione switch non contiene un'etichetta case con il valore costante specificato, si verifica un errore in fase di compilazione.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.

La destinazione di un' goto default istruzione è l'elenco di istruzioni nell'istruzione di inclusione switch immediata (istruzione switch), che contiene un' default etichetta.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 l' goto default istruzione non è racchiusa tra switch un'istruzione o l'istruzione di inclusione switch più vicina non contiene un' default etichetta, si verificherà un errore in fase di compilazione.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.

Un' goto istruzione non può uscire finally da un blocco (istruzione try).A goto statement cannot exit a finally block (The try statement). Quando un' goto istruzione si verifica all' finally interno di un blocco goto , la destinazione dell'istruzione deve trovarsi finally all'interno dello stesso blocco o in caso contrario si verifica un errore in fase di compilazione.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.

Un' goto istruzione viene eseguita come indicato di seguito:A goto statement is executed as follows:

  • Se l' goto istruzione esce da uno o più try blocchi con finally blocchi finally associati, il controllo viene inizialmente trasferito al blocco dell'istruzione più try interna.If the goto 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 il controllo raggiunge il punto finale di finally un blocco, il finally controllo viene trasferito al blocco della successiva istruzione di try inclusione.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. Questo processo viene ripetuto fino a finally quando non vengono eseguiti i try blocchi di tutte le istruzioni coinvolte.This process is repeated until the finally blocks of all intervening try statements have been executed.
  • Il controllo viene trasferito alla destinazione dell' goto istruzione.Control is transferred to the target of the goto statement.

Poiché un' goto istruzione trasferisce in modo incondizionato il controllo altrove, il goto punto finale di un'istruzione non è mai raggiungibile.Because a goto statement unconditionally transfers control elsewhere, the end point of a goto statement is never reachable.

Istruzione returnThe return statement

L' return istruzione restituisce il controllo al chiamante corrente della funzione in cui viene visualizzata return l'istruzione.The return statement returns control to the current caller of the function in which the return statement appears.

return_statement
    : 'return' expression? ';'
    ;

Un' return istruzione senza espressione può essere utilizzata solo in un membro di funzione che non calcola un valore, ovvero un metodo con il tipo di risultato (corpo del metodo void), la set funzione di accesso di una proprietà o un indicizzatore, add il funzioni remove di accesso e di un evento, un costruttore di istanza, un costruttore statico o un distruttore.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.

Un' return istruzione con un'espressione può essere utilizzata solo in un membro di funzione che calcola un valore, ovvero un metodo con un tipo di risultato non void, la get funzione di accesso di una proprietà o un indicizzatore o un operatore definito dall'utente.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. Una conversione implicita (conversioni implicite) deve esistere dal tipo dell'espressione al tipo restituito del membro della funzione contenitore.An implicit conversion (Implicit conversions) must exist from the type of the expression to the return type of the containing function member.

È inoltre possibile utilizzare le istruzioni return nel corpo di espressioni di funzione anonime (espressioni di funzione anonime) e partecipare alla determinazione delle conversioni esistenti per tali funzioni.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.

Si tratta di un errore in fase di compilazione return per un'istruzione da visualizzare finally in un blocco (istruzione try).It is a compile-time error for a return statement to appear in a finally block (The try statement).

Un' return istruzione viene eseguita come indicato di seguito:A return statement is executed as follows:

  • Se l' return istruzione specifica un'espressione, l'espressione viene valutata e il valore risultante viene convertito nel tipo restituito della funzione che lo contiene mediante una conversione implicita.If the return 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. Il risultato della conversione diventa il valore risultante prodotto dalla funzione.The result of the conversion becomes the result value produced by the function.
  • Se l' return istruzione è racchiusa tra uno o try più catch blocchi o con finally blocchi associati, il controllo viene inizialmente trasferito finally al blocco dell'istruzione try più interna.If the return statement is enclosed by one or more try or catch blocks with associated finally blocks, control is initially transferred to the finally block of the innermost try statement. Quando e se il controllo raggiunge il punto finale di finally un blocco, il finally controllo viene trasferito al blocco della successiva istruzione di try inclusione.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. Questo processo viene ripetuto fino a finally quando non vengono eseguiti i try blocchi di tutte le istruzioni di inclusione.This process is repeated until the finally blocks of all enclosing try statements have been executed.
  • Se la funzione che lo contiene non è una funzione asincrona, il controllo viene restituito al chiamante della funzione contenitore insieme al valore del risultato, se presente.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 la funzione contenitore è una funzione asincrona, il controllo viene restituito al chiamante corrente e il valore del risultato, se presente, viene registrato nell'attività restituita come descritto in (interfacce enumeratore).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).

Poiché un' return istruzione trasferisce in modo incondizionato il controllo altrove, il return punto finale di un'istruzione non è mai raggiungibile.Because a return statement unconditionally transfers control elsewhere, the end point of a return statement is never reachable.

Istruzione throwThe throw statement

L' throw istruzione genera un'eccezione.The throw statement throws an exception.

throw_statement
    : 'throw' expression? ';'
    ;

Un' throw istruzione con un'espressione genera il valore prodotto dalla valutazione dell'espressione.A throw statement with an expression throws the value produced by evaluating the expression. L'espressione deve indicare un valore del tipo System.Exceptiondi classe, di un tipo di classe che deriva da System.Exception o di un tipo di parametro di tipo che System.Exception ha (o una sottoclasse) come classe di base valida.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 la valutazione dell'espressione produce null, viene System.NullReferenceException invece generata un'eccezione.If evaluation of the expression produces null, a System.NullReferenceException is thrown instead.

Un' throw istruzione senza espressione può essere utilizzata solo in un catch blocco, nel qual caso tale istruzione genera di nuovo l'eccezione attualmente gestita da tale catch blocco.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.

Poiché un' throw istruzione trasferisce in modo incondizionato il controllo altrove, il throw punto finale di un'istruzione non è mai raggiungibile.Because a throw statement unconditionally transfers control elsewhere, the end point of a throw statement is never reachable.

Quando viene generata un'eccezione, il controllo viene trasferito alla prima catch clausola in un'istruzione contenitore try in grado di gestire l'eccezione.When an exception is thrown, control is transferred to the first catch clause in an enclosing try statement that can handle the exception. Il processo che si verifica dal punto dell'eccezione generata al momento del trasferimento del controllo a un gestore di eccezioni adatto è noto come propagazione delle eccezioni.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. La propagazione di un'eccezione è costituita dalla valutazione ripetuta dei catch passaggi seguenti fino a quando non viene trovata una clausola che corrisponde all'eccezione.Propagation of an exception consists of repeatedly evaluating the following steps until a catch clause that matches the exception is found. In questa descrizione, il punto di generazione è inizialmente la posizione in cui viene generata l'eccezione.In this description, the throw point is initially the location at which the exception is thrown.

  • Nel membro della funzione corrente, viene try esaminata ogni istruzione che racchiude il punto di generazione.In the current function member, each try statement that encloses the throw point is examined. Per ogni istruzione S, a partire dall'istruzione try più interna e terminando con try l'istruzione più esterna, vengono valutati i passaggi seguenti:For each statement S, starting with the innermost try statement and ending with the outermost try statement, the following steps are evaluated:

    • Se il S catch catch blocco di racchiude il punto di generazione e se S ha una o più clausole, le clausole vengono esaminate in ordine di aspetto per individuare un gestore appropriato per l'eccezione, in base alle regole specificate in try Sezione espressione try.If the try block of S encloses the throw point and if S has one or more catch clauses, the catch 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 viene individuata una clausola corrispondente catch , la propagazione delle eccezioni viene completata trasferendo il controllo al blocco catch della clausola.If a matching catch clause is located, the exception propagation is completed by transferring control to the block of that catch clause.

    • In caso contrario, try se il blocco catch o un S blocco di racchiude il punto di generazione e S se dispone finally di un blocco, il controllo viene finally trasferito nel blocco.Otherwise, if the try block or a catch block of S encloses the throw point and if S has a finally block, control is transferred to the finally block. Se il finally blocco genera un'altra eccezione, l'elaborazione dell'eccezione corrente viene terminata.If the finally block throws another exception, processing of the current exception is terminated. In caso contrario, quando il controllo raggiunge il punto finally finale del blocco, viene continuata l'elaborazione dell'eccezione corrente.Otherwise, when control reaches the end point of the finally block, processing of the current exception is continued.

  • Se un gestore di eccezioni non si trova nella chiamata della funzione corrente, la chiamata alla funzione viene terminata e si verifica una delle condizioni seguenti:If an exception handler was not located in the current function invocation, the function invocation is terminated, and one of the following occurs:

    • Se la funzione corrente è non asincrona, i passaggi precedenti vengono ripetuti per il chiamante della funzione con un punto di generazione corrispondente all'istruzione da cui il membro della funzione è stato richiamato.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 la funzione corrente è asincrona e restituisce un'attività, l'eccezione viene registrata nell'attività return, che viene inserita in uno stato di errore o annullato, come descritto in interfacce dell'enumeratore.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 la funzione corrente è asincrona e restituisce un risultato null, viene notificato il contesto di sincronizzazione del thread corrente come descritto in interfacce enumerabili.If the current function is async and void-returning, the synchronization context of the current thread is notified as described in Enumerable interfaces.

  • Se l'elaborazione delle eccezioni termina tutte le chiamate del membro della funzione nel thread corrente, a indicare che il thread non ha alcun gestore per l'eccezione, il thread viene interrotto.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. L'effetto di tale interruzione è definito dall'implementazione.The impact of such termination is implementation-defined.

Istruzione tryThe try statement

L' try istruzione fornisce un meccanismo per intercettare le eccezioni che si verificano durante l'esecuzione di un blocco.The try statement provides a mechanism for catching exceptions that occur during execution of a block. L' try istruzione offre inoltre la possibilità di specificare un blocco di codice che viene sempre eseguito quando il controllo lascia l' try istruzione.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
    ;

Esistono tre possibili forme di try istruzioni:There are three possible forms of try statements:

  • Un try blocco seguito da uno o più catch blocchi.A try block followed by one or more catch blocks.
  • Un try blocco seguito da un finally blocco.A try block followed by a finally block.
  • Un try blocco seguito da uno o più catch blocchi seguiti da finally un blocco.A try block followed by one or more catch blocks followed by a finally block.

Quando una clausola catch specifica un exception_specifier, il tipo deve essere System.Exception, un tipo che deriva da System.Exception o un tipo di parametro di tipo con System.Exception (o una sottoclasse) come classe di base valida.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 una clausola catch specifica sia un exception_specifier con un identificatore, viene dichiarata una variabile di eccezione con il nome e il tipo specificati.When a catch clause specifies both an exception_specifier with an identifier, an exception variable of the given name and type is declared. La variabile di eccezione corrisponde a una variabile locale con un ambito che si estende catch sulla clausola.The exception variable corresponds to a local variable with a scope that extends over the catch clause. Durante l'esecuzione del exception_filter e del blocco, la variabile di eccezione rappresenta l'eccezione attualmente gestita.During execution of the exception_filter and block, the exception variable represents the exception currently being handled. Ai fini del controllo di assegnazione definito, la variabile di eccezione viene considerata definitivamente assegnata nell'intero ambito.For purposes of definite assignment checking, the exception variable is considered definitely assigned in its entire scope.

A meno che catch una clausola non includa un nome di variabile di eccezione, non è possibile accedere all'oggetto eccezione catch nel filtro e nel blocco.Unless a catch clause includes an exception variable name, it is impossible to access the exception object in the filter and catch block.

Una clausola catch che non specifica un exception_specifier è detta clausola generale catch.A catch clause that does not specify an exception_specifier is called a general catch clause.

Alcuni linguaggi di programmazione possono supportare eccezioni che non possono essere rappresentate come un oggetto derivato System.Exceptionda, sebbene tali eccezioni non possano mai essere C# generate dal codice.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. È possibile catch utilizzare una clausola generale per intercettare tali eccezioni.A general catch clause may be used to catch such exceptions. Pertanto, una clausola catch generale è semanticamente diversa da quella che specifica il tipo System.Exception, in quanto il primo può rilevare anche eccezioni da altri linguaggi.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.

Per individuare un gestore per un'eccezione, catch le clausole vengono esaminate in ordine lessicale.In order to locate a handler for an exception, catch clauses are examined in lexical order. Se una catch clausola specifica un tipo ma nessun filtro eccezioni, si tratta di un errore in fase di compilazione per catch una clausola successiva nella try stessa istruzione per specificare un tipo che è uguale a o è derivato da tale 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 una catch clausola non specifica alcun tipo e nessun filtro, deve essere l'ultima catch clausola try dell'istruzione.If a catch clause specifies no type and no filter, it must be the last catch clause for that try statement.

All'interno catch di un blocco throw , un'istruzione (istruzione throw) senza espressione può essere utilizzata per generare di nuovo catch l'eccezione rilevata dal blocco.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. Le assegnazioni a una variabile di eccezione non modificano l'eccezione generata nuovamente.Assignments to an exception variable do not alter the exception that is re-thrown.

Nell'esempioIn 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);
        }
    }
}

il metodo F rileva un'eccezione, scrive alcune informazioni di diagnostica nella console, modifica la variabile di eccezione e genera nuovamente l'eccezione.the method F catches an exception, writes some diagnostic information to the console, alters the exception variable, and re-throws the exception. L'eccezione generata di nuovo è l'eccezione originale, quindi l'output prodotto è:The exception that is re-thrown is the original exception, so the output produced is:

Exception in F: G
Exception in Main: G

Se è stato generato e il primo blocco catch anziché rigenerare l'eccezione corrente, l'output prodotto sarà il seguente: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

Si tratta di un errore in fase di compilazione breakper continueun'istruzione goto , o per trasferire il controllo all' finally esterno di un blocco.It is a compile-time error for a break, continue, or goto statement to transfer control out of a finally block. Quando un' breakistruzione continue, o goto si verifica in un finally blocco, la destinazione dell'istruzione deve trovarsi all'interno dello finally stesso blocco o in caso contrario si verifica un errore in fase di compilazione.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.

Si tratta di un errore in fase di compilazione return per un'istruzione che si finally verifica in un blocco.It is a compile-time error for a return statement to occur in a finally block.

Un' try istruzione viene eseguita come indicato di seguito:A try statement is executed as follows:

  • Il try controllo viene trasferito nel blocco.Control is transferred to the try block.

  • Quando e se il controllo raggiunge il punto finale del try blocco:When and if control reaches the end point of the try block:

    • Se l' try istruzione ha un finally blocco, il finally blocco viene eseguito.If the try statement has a finally block, the finally block is executed.
    • Il controllo viene trasferito al punto finale dell' try istruzione.Control is transferred to the end point of the try statement.
  • Se un'eccezione viene propagata all' try istruzione durante l'esecuzione try del blocco:If an exception is propagated to the try statement during execution of the try block:

    • Le catch clausole, se presenti, vengono esaminate in ordine di aspetto per individuare un gestore appropriato per l'eccezione.The catch clauses, if any, are examined in order of appearance to locate a suitable handler for the exception. Se una catch clausola non specifica un tipo o specifica il tipo di eccezione o un tipo di base del tipo di eccezione:If a catch clause does not specify a type, or specifies the exception type or a base type of the exception type:
      • Se la catch clausola dichiara una variabile di eccezione, l'oggetto eccezione viene assegnato alla variabile di eccezione.If the catch clause declares an exception variable, the exception object is assigned to the exception variable.
      • Se la catch clausola dichiara un filtro eccezioni, il filtro viene valutato.If the catch clause declares an exception filter, the filter is evaluated. Se restituisce false, la clausola catch non è una corrispondenza e la ricerca continua con le clausole successive catch per un gestore appropriato.If it evaluates to false, the catch clause is not a match, and the search continues through any subsequent catch clauses for a suitable handler.
      • In caso contrario catch , la clausola viene considerata una corrispondenza e il controllo viene trasferito al catch blocco corrispondente.Otherwise, the catch clause is considered a match, and control is transferred to the matching catch block.
      • Quando e se il controllo raggiunge il punto finale del catch blocco:When and if control reaches the end point of the catch block:
        • Se l' try istruzione ha un finally blocco, il finally blocco viene eseguito.If the try statement has a finally block, the finally block is executed.
        • Il controllo viene trasferito al punto finale dell' try istruzione.Control is transferred to the end point of the try statement.
      • Se un'eccezione viene propagata all' try istruzione durante l'esecuzione catch del blocco:If an exception is propagated to the try statement during execution of the catch block:
        • Se l' try istruzione ha un finally blocco, il finally blocco viene eseguito.If the try statement has a finally block, the finally block is executed.
        • L'eccezione viene propagata alla successiva istruzione di try inclusione.The exception is propagated to the next enclosing try statement.
    • Se l' try istruzione non catch ha clausole o se nessuna catch clausola corrisponde all'eccezione:If the try statement has no catch clauses or if no catch clause matches the exception:
      • Se l' try istruzione ha un finally blocco, il finally blocco viene eseguito.If the try statement has a finally block, the finally block is executed.
      • L'eccezione viene propagata alla successiva istruzione di try inclusione.The exception is propagated to the next enclosing try statement.

Le istruzioni di un finally blocco vengono sempre eseguite quando il controllo lascia try un'istruzione.The statements of a finally block are always executed when control leaves a try statement. Questo vale se il trasferimento del controllo si verifica in seguito all'esecuzione normale, in seguito breakall'esecuzione di un'istruzione, continue, gotoo o return a seguito della propagazione di try un'eccezione dal istruzione.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 viene generata un'eccezione durante l'esecuzione di finally un blocco e non viene rilevata all'interno dello stesso blocco finally, l'eccezione viene propagata try alla successiva istruzione di inclusione.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 è in corso la propagazione di un'altra eccezione, l'eccezione viene persa.If another exception was in the process of being propagated, that exception is lost. Il processo di propagazione di un'eccezione viene discusso ulteriormente nella descrizione dell' throw istruzione (istruzione throw).The process of propagating an exception is discussed further in the description of the throw statement (The throw statement).

Il try blocco di un' try istruzione è raggiungibile se l' try istruzione è raggiungibile.The try block of a try statement is reachable if the try statement is reachable.

Un catch blocco di un' try istruzione è raggiungibile se l' try istruzione è raggiungibile.A catch block of a try statement is reachable if the try statement is reachable.

Il finally blocco di un' try istruzione è raggiungibile se l' try istruzione è raggiungibile.The finally block of a try statement is reachable if the try statement is reachable.

Il punto finale di un' try istruzione è raggiungibile se si verificano entrambe le condizioni seguenti:The end point of a try statement is reachable if both of the following are true:

  • Il punto finale del try blocco è raggiungibile oppure è raggiungibile il punto finale di almeno un catch blocco.The end point of the try block is reachable or the end point of at least one catch block is reachable.
  • Se è finally presente un blocco, il punto finale finally del blocco è raggiungibile.If a finally block is present, the end point of the finally block is reachable.

Istruzioni checked e uncheckedThe checked and unchecked statements

Le checked istruzioni unchecked e vengono utilizzate per controllare il contesto di controllo dell'overflow per le conversioni e le operazioni aritmetiche di tipo integrale.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
    ;

L' checked istruzione fa in modo che tutte le espressioni del blocco vengano valutate in un contesto controllato unchecked e l'istruzione provochi la valutazione di tutte le espressioni del blocco in un contesto non verificato.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.

Le checked istruzioni unchecked echecked sono esattamente equivalenti agli operatori unchecked and (gli operatori checked e unchecked), ad eccezione del fatto che operano su blocchi anziché su espressioni.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.

Istruzione lockThe lock statement

L' lock istruzione ottiene il blocco di esclusione reciproca per un determinato oggetto, esegue un'istruzione e quindi rilascia il blocco.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
    ;

L'espressione di un'istruzione lock deve indicare un valore di un tipo noto come reference_type.The expression of a lock statement must denote a value of a type known to be a reference_type. Non viene mai eseguita alcuna conversione boxing implicita (conversioni boxing) per l'espressione di un'istruzione lock e pertanto si tratta di un errore in fase di compilazione perché l'espressione denoti un valore di 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.

Un' lock istruzione nel formatoA lock statement of the form

lock (x) ...

dove x è un'espressione di un reference_type, è esattamente 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);
}

con la differenza che x viene valutato una sola volta.except that x is only evaluated once.

Mentre viene mantenuto un blocco di esclusione reciproca, il codice in esecuzione nello stesso thread di esecuzione può anche ottenere e rilasciare il blocco.While a mutual-exclusion lock is held, code executing in the same execution thread can also obtain and release the lock. Tuttavia, il codice in esecuzione in altri thread viene bloccato dall'ottenimento del blocco fino al rilascio del blocco.However, code executing in other threads is blocked from obtaining the lock until the lock is released.

Non System.Type è consigliabile bloccare gli oggetti per sincronizzare l'accesso ai dati statici.Locking System.Type objects in order to synchronize access to static data is not recommended. Un altro codice potrebbe bloccarsi sullo stesso tipo, che può causare un deadlock.Other code might lock on the same type, which can result in deadlock. Un approccio migliore consiste nel sincronizzare l'accesso ai dati statici bloccando un oggetto statico privato.A better approach is to synchronize access to static data by locking a private static object. Esempio: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) {
            ...
        }
    }
}

Istruzione usingThe using statement

L' using istruzione ottiene una o più risorse, esegue un'istruzione e quindi Elimina la risorsa.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
    ;

Una risorsa è una classe o uno struct che System.IDisposableimplementa, che include un singolo metodo senza parametri Disposedenominato.A resource is a class or struct that implements System.IDisposable, which includes a single parameterless method named Dispose. Il codice che usa una risorsa può chiamare Dispose per indicare che la risorsa non è più necessaria.Code that is using a resource can call Dispose to indicate that the resource is no longer needed. Se Dispose non viene chiamato, l'eliminazione automatica viene infine eseguita come conseguenza del Garbage Collection.If Dispose is not called, then automatic disposal eventually occurs as a consequence of garbage collection.

Se il formato di resource_acquisition è local_variable_declaration , il tipo di local_variable_declaration deve essere dynamic o un tipo che può essere convertito in modo implicito in 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 il formato di resource_acquisition è Expression , l'espressione deve essere convertibile in modo implicito in System.IDisposable.If the form of resource_acquisition is expression then this expression must be implicitly convertible to System.IDisposable.

Le variabili locali dichiarate in un resource_acquisition sono di sola lettura e devono includere un inizializzatore.Local variables declared in a resource_acquisition are read-only, and must include an initializer. Si verifica un errore in fase di compilazione se l'istruzione incorporata tenta di modificare queste variabili locali (tramite ++ assegnazione -- o gli operatori e), di prenderne l'indirizzo o di ref passarle come parametri o out .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.

Un' using istruzione viene convertita in tre parti: acquisizione, utilizzo e eliminazione.A using statement is translated into three parts: acquisition, usage, and disposal. L'utilizzo della risorsa viene racchiuso in modo implicito in un' try istruzione che include una finally clausola.Usage of the resource is implicitly enclosed in a try statement that includes a finally clause. Questa finally clausola Elimina la risorsa.This finally clause disposes of the resource. Se viene null acquisita una risorsa, non viene effettuata Dispose alcuna chiamata a e non viene generata alcuna eccezione.If a null resource is acquired, then no call to Dispose is made, and no exception is thrown. Se la risorsa è di tipo dynamic , viene convertita dinamicamente tramite una conversione dinamica implicita (conversioni dinamiche implicite) IDisposable in durante l'acquisizione, in modo da garantire che la conversione venga eseguita prima dell'utilizzo e eliminazione.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.

Un' using istruzione nel formatoA using statement of the form

using (ResourceType resource = expression) statement

corrisponde a una delle tre espansioni possibili.corresponds to one of three possible expansions. Quando ResourceType è un tipo di valore non nullable, l'espansione èWhen ResourceType is a non-nullable value type, the expansion is

{
    ResourceType resource = expression;
    try {
        statement;
    }
    finally {
        ((IDisposable)resource).Dispose();
    }
}

In caso contrario ResourceType , quando è un tipo di valore nullable o un tipo dynamicdi riferimento diverso da, l'espansione è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();
    }
}

In caso contrario ResourceType , dynamicquando è, l'espansione èOtherwise, when ResourceType is dynamic, the expansion is

{
    ResourceType resource = expression;
    IDisposable d = (IDisposable)resource;
    try {
        statement;
    }
    finally {
        if (d != null) d.Dispose();
    }
}

In una delle due espansioni resource , la variabile è di sola lettura nell'istruzione incorporata e d la variabile è inaccessibile in e invisibile a, l'istruzione incorporata.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.

Un'implementazione di può implementare una determinata istruzione using in modo diverso, ad esempio per motivi di prestazioni, purché il comportamento sia coerente con l'espansione precedente.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.

Un' using istruzione nel formatoA using statement of the form

using (expression) statement

presenta le stesse tre espansioni possibili.has the same three possible expansions. In questo caso ResourceType è implicitamente il tipo in fase expressiondi compilazione di, se presente.In this case ResourceType is implicitly the compile-time type of the expression, if it has one. In caso contrario IDisposable ResourceType, l'interfaccia stessa viene utilizzata come.Otherwise the interface IDisposable itself is used as the ResourceType. La resource variabile è inaccessibile in e invisibile a, l'istruzione incorporata.The resource variable is inaccessible in, and invisible to, the embedded statement.

Quando un resource_acquisition assume il formato di un local_variable_declaration, è possibile acquisire più risorse di un determinato tipo.When a resource_acquisition takes the form of a local_variable_declaration, it is possible to acquire multiple resources of a given type. Un' using istruzione nel formatoA using statement of the form

using (ResourceType r1 = e1, r2 = e2, ..., rN = eN) statement

è esattamente equivalente a una sequenza di istruzioni using nidificate:is precisely equivalent to a sequence of nested using statements:

using (ResourceType r1 = e1)
    using (ResourceType r2 = e2)
        ...
            using (ResourceType rN = eN)
                statement

Nell'esempio seguente viene creato un file log.txt denominato e vengono scritte due righe di testo nel file.The example below creates a file named log.txt and writes two lines of text to the file. Nell'esempio viene quindi aperto lo stesso file per la lettura e la copia delle righe di testo contenute nella 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);
            }

        }
    }
}

Poiché le classi TextReadereimplementano l' IDisposable interfaccia, l'esempio può using utilizzare le istruzioni per garantire che il file sottostante venga chiuso correttamente dopo le operazioni di scrittura o lettura. TextWriterSince 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.

Istruzione yieldThe yield statement

L' yield istruzione viene utilizzata in un blocco iteratore (blocchi) per restituire un valore all'oggetto enumeratore (oggetti enumeratore) o a un oggetto enumerabile (oggetti enumerabile) di un iteratore o per segnalare la fine dell'iterazione.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' ';'
    ;

yieldnon è una parola riservata. ha un significato speciale solo quando viene usato immediatamente prima return di break una parola chiave o.yield is not a reserved word; it has special meaning only when used immediately before a return or break keyword. In altri contesti, yield può essere usato come identificatore.In other contexts, yield can be used as an identifier.

Esistono diverse restrizioni per la posizione in yield cui può essere visualizzata un'istruzione, come descritto di seguito.There are several restrictions on where a yield statement can appear, as described in the following.

  • Si tratta di un errore in fase di compilazione per un'istruzione yield (di uno dei due form) che viene visualizzata all'esterno di method_body, operator_body o accessor_bodyIt is a compile-time error for a yield statement (of either form) to appear outside a method_body, operator_body or accessor_body
  • Si tratta di un errore in fase di compilazione yield per l'inclusione di un'istruzione (di uno dei due form) all'interno di una funzione anonima.It is a compile-time error for a yield statement (of either form) to appear inside an anonymous function.
  • Si tratta di un errore in fase di compilazione yield per l' finally inclusione di un'istruzione (di uno dei due form try ) nella clausola di un'istruzione.It is a compile-time error for a yield statement (of either form) to appear in the finally clause of a try statement.
  • Si tratta di un errore in fase di compilazione yield return per un'istruzione che viene visualizzata try in un punto qualsiasi catch di un'istruzione che contiene clausole.It is a compile-time error for a yield return statement to appear anywhere in a try statement that contains any catch clauses.

Nell'esempio seguente vengono illustrati alcuni usi validi e yield non validi delle istruzioni.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
}

Una conversione implicita (conversioni implicite) deve esistere dal tipo dell'espressione nell' yield return istruzione al tipo yield (tipodi risultato) dell'iteratore.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.

Un' yield return istruzione viene eseguita come indicato di seguito:A yield return statement is executed as follows:

  • L'espressione specificata nell'istruzione viene valutata, convertita in modo implicito nel tipo yield e assegnata Current alla proprietà dell'oggetto enumeratore.The expression given in the statement is evaluated, implicitly converted to the yield type, and assigned to the Current property of the enumerator object.
  • L'esecuzione del blocco iteratore è sospesa.Execution of the iterator block is suspended. Se l' yield return istruzione si trova all'interno di try uno o più blocchi finally , i blocchi associati non vengono eseguiti in questo momento.If the yield return statement is within one or more try blocks, the associated finally blocks are not executed at this time.
  • Il MoveNext metodo dell'oggetto enumeratore viene true restituito al chiamante, a indicare che l'oggetto enumeratore è stato spostato correttamente sull'elemento successivo.The MoveNext method of the enumerator object returns true to its caller, indicating that the enumerator object successfully advanced to the next item.

La chiamata successiva al MoveNext metodo dell'oggetto enumeratore riprende l'esecuzione del blocco iteratore dal punto in cui è stata sospesa l'ultima volta.The next call to the enumerator object's MoveNext method resumes execution of the iterator block from where it was last suspended.

Un' yield break istruzione viene eseguita come indicato di seguito:A yield break statement is executed as follows:

  • Se l' yield break istruzione è racchiusa tra uno o try più blocchi con finally finally blocchi associati, il controllo viene inizialmente trasferito al blocco dell'istruzione try più interna.If the yield break statement is enclosed by 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 il controllo raggiunge il punto finale di finally un blocco, il finally controllo viene trasferito al blocco della successiva istruzione di try inclusione.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. Questo processo viene ripetuto fino a finally quando non vengono eseguiti i try blocchi di tutte le istruzioni di inclusione.This process is repeated until the finally blocks of all enclosing try statements have been executed.
  • Il controllo viene restituito al chiamante del blocco iteratore.Control is returned to the caller of the iterator block. Si tratta del MoveNext metodo o Dispose del metodo dell'oggetto enumeratore.This is either the MoveNext method or Dispose method of the enumerator object.

Poiché un' yield break istruzione trasferisce in modo incondizionato il controllo altrove, il yield break punto finale di un'istruzione non è mai raggiungibile.Because a yield break statement unconditionally transfers control elsewhere, the end point of a yield break statement is never reachable.