InstructionsStatements

C#fournit une série d’instructions.C# provides a variety of statements. La plupart de ces instructions seront familières aux développeurs qui ont programmé en C C++et.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
    ;

Le embedded_statement non terminal est utilisé pour les instructions qui s’affichent dans d’autres instructions.The embedded_statement nonterminal is used for statements that appear within other statements. L’utilisation de embedded_statement au lieu d’une instruction exclut l’utilisation d’instructions de déclaration et d’instructions étiquetées dans ces contextes.The use of embedded_statement rather than statement excludes the use of declaration statements and labeled statements in these contexts. L’exempleThe example

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

génère une erreur au moment de la compilation, car une instruction if requiert un embedded_statement plutôt qu’une instruction pour sa branche if.results in a compile-time error because an if statement requires an embedded_statement rather than a statement for its if branch. Si ce code est autorisé, la variable i est déclarée, mais elle n’a jamais été utilisée.If this code were permitted, then the variable i would be declared, but it could never be used. Notez, toutefois, qu’en plaçant ila déclaration de dans un bloc, l’exemple est valide.Note, however, that by placing i's declaration in a block, the example is valid.

Points de terminaison et accessibilitéEnd points and reachability

Chaque instruction a un point de terminaison.Every statement has an end point. En termes intuitifs, le point de terminaison d’une instruction correspond à l’emplacement qui suit immédiatement l’instruction.In intuitive terms, the end point of a statement is the location that immediately follows the statement. Les règles d’exécution des instructions composites (instructions qui contiennent des instructions incorporées) spécifient l’action qui est effectuée lorsque le contrôle atteint le point de terminaison d’une instruction incorporée.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. Par exemple, lorsque le contrôle atteint le point de terminaison d’une instruction dans un bloc, le contrôle est transféré à l’instruction suivante dans le bloc.For example, when control reaches the end point of a statement in a block, control is transferred to the next statement in the block.

Si une instruction peut être atteinte par l’exécution, l’instruction est dite accessible.If a statement can possibly be reached by execution, the statement is said to be reachable. À l’inverse, s’il n’est pas possible qu’une instruction soit exécutée, l’instruction est dite inaccessible.Conversely, if there is no possibility that a statement will be executed, the statement is said to be unreachable.

Dans l’exempleIn the example

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

le deuxième appel de Console.WriteLine est inaccessible, car il n’est pas possible que l’instruction soit exécutée.the second invocation of Console.WriteLine is unreachable because there is no possibility that the statement will be executed.

Un avertissement est signalé si le compilateur détermine qu’une instruction est inaccessible.A warning is reported if the compiler determines that a statement is unreachable. Il ne s’agit pas d’une erreur spécifique pour qu’une instruction soit inaccessible.It is specifically not an error for a statement to be unreachable.

Pour déterminer si une instruction ou un point de terminaison particulier est accessible, le compilateur effectue une analyse de workflow en fonction des règles d’accessibilité définies pour chaque instruction.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’analyse du workflow prend en compte les valeurs des expressions constantes (expressions constantes) qui contrôlent le comportement des instructions, mais les valeurs possibles des expressions non constantes ne sont pas prises en compte.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. En d’autres termes, à des fins d’analyse de workflow de contrôle, une expression non constante d’un type donné est considérée comme ayant n’importe quelle valeur possible de ce type.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.

Dans l’exempleIn the example

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

l’expression booléenne de l' if instruction est une expression constante, car les deux opérandes == de l’opérateur sont des constantes.the boolean expression of the if statement is a constant expression because both operands of the == operator are constants. Étant donné que l’expression constante est évaluée au moment de la compilation false, produisant Console.WriteLine la valeur, l’appel est considéré comme inaccessible.As the constant expression is evaluated at compile-time, producing the value false, the Console.WriteLine invocation is considered unreachable. Toutefois, si i est remplacé par une variable localeHowever, if i is changed to be a local variable

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

l' Console.WriteLine appel est considéré comme accessible, même si, en réalité, il ne sera jamais exécuté.the Console.WriteLine invocation is considered reachable, even though, in reality, it will never be executed.

Le bloc d’un membre de fonction est toujours considéré comme accessible.The block of a function member is always considered reachable. En évaluant successivement les règles d’accessibilité de chaque instruction dans un bloc, vous pouvez déterminer l’accessibilité d’une instruction donnée.By successively evaluating the reachability rules of each statement in a block, the reachability of any given statement can be determined.

Dans l’exempleIn the example

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

l’accessibilité de la seconde Console.WriteLine est déterminée comme suit :the reachability of the second Console.WriteLine is determined as follows:

  • La première Console.WriteLine instruction d’expression est accessible car le bloc de la F méthode est accessible.The first Console.WriteLine expression statement is reachable because the block of the F method is reachable.
  • Le point de terminaison de la Console.WriteLine première instruction d’expression est accessible car cette instruction est accessible.The end point of the first Console.WriteLine expression statement is reachable because that statement is reachable.
  • L' if instruction est accessible parce que le point de terminaison de la Console.WriteLine première instruction d’expression est accessible.The if statement is reachable because the end point of the first Console.WriteLine expression statement is reachable.
  • La deuxième Console.WriteLine instruction d’expression est accessible parce que l’expression booléenne de if l’instruction n’a pas la valeur falsede constante.The second Console.WriteLine expression statement is reachable because the boolean expression of the if statement does not have the constant value false.

Il existe deux situations dans lesquelles il s’agit d’une erreur de compilation pour que le point de terminaison d’une instruction soit accessible :There are two situations in which it is a compile-time error for the end point of a statement to be reachable:

  • Étant donné switch que l’instruction ne permet pas à une section switch de passer à la section switch suivante, il s’agit d’une erreur de compilation pour le point de terminaison de la liste d’instructions d’une section switch à atteindre.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. Si cette erreur se produit, cela indique généralement qu’une break instruction est manquante.If this error occurs, it is typically an indication that a break statement is missing.
  • Il s’agit d’une erreur au moment de la compilation pour le point de terminaison du bloc d’un membre de fonction qui calcule une valeur à atteindre.It is a compile-time error for the end point of the block of a function member that computes a value to be reachable. Si cette erreur se produit, cela indique généralement qu’une return instruction est manquante.If this error occurs, it typically is an indication that a return statement is missing.

BlocsBlocks

Un bloc autorise l’écriture de plusieurs instructions dans les contextes où une seule instruction est autorisée.A block permits multiple statements to be written in contexts where a single statement is allowed.

block
    : '{' statement_list? '}'
    ;

Un bloc se compose d’un statement_list facultatif (listes d’instructions), placé entre accolades.A block consists of an optional statement_list (Statement lists), enclosed in braces. Si la liste d’instructions est omise, le bloc est dit vide.If the statement list is omitted, the block is said to be empty.

Un bloc peut contenir des instructions de déclaration (instructions de déclaration).A block may contain declaration statements (Declaration statements). La portée d’une variable locale ou d’une constante déclarée dans un bloc est le bloc.The scope of a local variable or constant declared in a block is the block.

Un bloc est exécuté comme suit :A block is executed as follows:

  • Si le bloc est vide, le contrôle est transféré vers le point de terminaison du bloc.If the block is empty, control is transferred to the end point of the block.
  • Si le bloc n’est pas vide, le contrôle est transféré à la liste d’instructions.If the block is not empty, control is transferred to the statement list. Quand et si le contrôle atteint le point de terminaison de la liste d’instructions, le contrôle est transféré vers le point de terminaison du bloc.When and if control reaches the end point of the statement list, control is transferred to the end point of the block.

La liste d’instructions d’un bloc est accessible si le bloc lui-même est accessible.The statement list of a block is reachable if the block itself is reachable.

Le point de terminaison d’un bloc est accessible si le bloc est vide ou si le point de terminaison de la liste d’instructions est accessible.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 bloc qui contient une ou plusieurs yield instructions (l’instruction yield) est appelé un bloc itérateur.A block that contains one or more yield statements (The yield statement) is called an iterator block. Les blocs itérateurs sont utilisés pour implémenter des membres de fonction en tant qu’itérateurs (itérateurs).Iterator blocks are used to implement function members as iterators (Iterators). Certaines restrictions supplémentaires s’appliquent aux blocs Iterator :Some additional restrictions apply to iterator blocks:

  • Il s’agit d’une erreur de compilation pour return qu’une instruction apparaisse dans un bloc itérateur yield return (les instructions sont autorisées).It is a compile-time error for a return statement to appear in an iterator block (but yield return statements are permitted).
  • Il s’agit d’une erreur au moment de la compilation pour qu’un bloc itérateur contienne un contexte non sécurisé (contextes non sécurisés).It is a compile-time error for an iterator block to contain an unsafe context (Unsafe contexts). Un bloc itérateur définit toujours un contexte sécurisé, même quand sa déclaration est imbriquée dans un contexte unsafe.An iterator block always defines a safe context, even when its declaration is nested in an unsafe context.

Listes d’instructionsStatement lists

Une liste d’instructions se compose d’une ou de plusieurs instructions écrites en séquence.A statement list consists of one or more statements written in sequence. Les listes d’instructions se trouvent dansles blocs (blocs) et dans switch_blocks (instruction switch).Statement lists occur in blocks (Blocks) and in switch_blocks (The switch statement).

statement_list
    : statement+
    ;

Une liste d’instructions est exécutée en transférant le contrôle à la première instruction.A statement list is executed by transferring control to the first statement. Quand et si le contrôle atteint le point de terminaison d’une instruction, le contrôle est transféré à l’instruction suivante.When and if control reaches the end point of a statement, control is transferred to the next statement. Quand et si le contrôle atteint le point de terminaison de la dernière instruction, le contrôle est transféré vers le point de terminaison de la liste d’instructions.When and if control reaches the end point of the last statement, control is transferred to the end point of the statement list.

Une instruction dans une liste d’instructions est accessible si au moins l’une des conditions suivantes est vraie :A statement in a statement list is reachable if at least one of the following is true:

  • L’instruction est la première instruction et la liste d’instructions elle-même est accessible.The statement is the first statement and the statement list itself is reachable.
  • Le point de terminaison de l’instruction précédente est accessible.The end point of the preceding statement is reachable.
  • L’instruction est une instruction étiquetée et l’étiquette est référencée par une goto instruction accessible.The statement is a labeled statement and the label is referenced by a reachable goto statement.

Le point de terminaison d’une liste d’instructions est accessible si le point de terminaison de la dernière instruction de la liste est accessible.The end point of a statement list is reachable if the end point of the last statement in the list is reachable.

Instruction videThe empty statement

Un empty_statement ne fait rien.An empty_statement does nothing.

empty_statement
    : ';'
    ;

Une instruction vide est utilisée lorsqu’il n’y a aucune opération à effectuer dans un contexte où une instruction est requise.An empty statement is used when there are no operations to perform in a context where a statement is required.

L’exécution d’une instruction vide transfère simplement le contrôle au point de terminaison de l’instruction.Execution of an empty statement simply transfers control to the end point of the statement. Ainsi, le point de terminaison d’une instruction vide est accessible si l’instruction vide est accessible.Thus, the end point of an empty statement is reachable if the empty statement is reachable.

Une instruction vide peut être utilisée lors de l' while écriture d’une instruction avec un corps NULL :An empty statement can be used when writing a while statement with a null body:

bool ProcessMessage() {...}

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

En outre, une instruction vide peut être utilisée pour déclarer une étiquette juste avant la fermeture}«» d’un bloc :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: ;
}

Instructions étiquetéesLabeled statements

Un labeled_statement permet à une instruction d’être précédée d’une étiquette.A labeled_statement permits a statement to be prefixed by a label. Les instructions étiquetées sont autorisées dans des blocs, mais ne sont pas autorisées en tant qu’instructions incorporées.Labeled statements are permitted in blocks, but are not permitted as embedded statements.

labeled_statement
    : identifier ':' statement
    ;

Une instruction étiquetée déclare une étiquette portant le nom donné par l' identificateur.A labeled statement declares a label with the name given by the identifier. L’étendue d’une étiquette est le bloc entier dans lequel l’étiquette est déclarée, y compris les blocs imbriqués.The scope of a label is the whole block in which the label is declared, including any nested blocks. Il s’agit d’une erreur au moment de la compilation pour deux étiquettes portant le même nom pour lesquelles des étendues se chevauchent.It is a compile-time error for two labels with the same name to have overlapping scopes.

Une étiquette peut être référencée à goto partir d’instructions (l’instruction goto) dans la portée de l’étiquette.A label can be referenced from goto statements (The goto statement) within the scope of the label. Cela signifie que goto les instructions peuvent transférer le contrôle dans les blocs et hors des blocs, mais jamais dans des blocs.This means that goto statements can transfer control within blocks and out of blocks, but never into blocks.

Les étiquettes ont leur propre espace de déclaration et n’interfèrent pas avec d’autres identificateurs.Labels have their own declaration space and do not interfere with other identifiers. L’exempleThe example

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

est valide et utilise le nom x en tant que paramètre et étiquette.is valid and uses the name x as both a parameter and a label.

L’exécution d’une instruction étiquetée correspond exactement à l’exécution de l’instruction qui suit l’étiquette.Execution of a labeled statement corresponds exactly to execution of the statement following the label.

Outre l’accessibilité fournie par le workflow normal de contrôle, une instruction étiquetée est accessible si l’étiquette est référencée par une goto instruction accessible.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. Titre Si une goto instruction est à l' try intérieur d’un finally qui comprend un bloc et que l’instruction étiquetée est en dehors de finally la try, et que le point de terminaison du bloc est inaccessible, l’instruction étiquetée n’est pas accessible à partir de cette goto instruction.)(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.)

Instructions de déclarationDeclaration statements

Un declaration_statement déclare une variable locale ou une constante.A declaration_statement declares a local variable or constant. Les instructions de déclaration sont autorisées dans des blocs, mais ne sont pas autorisées en tant qu’instructions incorporées.Declaration statements are permitted in blocks, but are not permitted as embedded statements.

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

Déclarations de variables localesLocal variable declarations

Un local_variable_declaration déclare une ou plusieurs variables locales.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
    ;

Le local_variable_type d’un local_variable_declaration spécifie directement le type des variables introduites par la déclaration, ou indique avec l’identificateur var que le type doit être déduit en fonction d’un initialiseur.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. Le type est suivi d’une liste de local_variable_declarators, chacun d’entre eux introduisant une nouvelle variable.The type is followed by a list of local_variable_declarators, each of which introduces a new variable. Un local_variable_declarator se compose d’un identificateur qui nomme la variable, éventuellement suivie d’un jeton « = » et d’un local_variable_initializer qui donne la valeur initiale de la variable.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.

Dans le contexte d’une déclaration de variable locale, l’identificateur var agit comme un mot clé contextuel (Mots clés). Quand local_variable_type est spécifié comme var et qu’aucun type nommé var n’est dans la portée, la déclaration est une déclaration de variable locale implicitement typée, dont le type est déduit du type de l’expression d’initialiseur associée.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. Les déclarations de variables locales implicitement typées sont soumises aux restrictions suivantes :Implicitly typed local variable declarations are subject to the following restrictions:

  • Le local_variable_declaration ne peut pas inclure plusieurs local_variable_declarators.The local_variable_declaration cannot include multiple local_variable_declarators.
  • Local_variable_declarator doit inclure un local_variable_initializer.The local_variable_declarator must include a local_variable_initializer.
  • Local_variable_initializer doit être une expression.The local_variable_initializer must be an expression.
  • L' expression d’initialiseur doit avoir un type au moment de la compilation.The initializer expression must have a compile-time type.
  • L' expression d’initialiseur ne peut pas faire référence à la variable déclarée elle-mêmeThe initializer expression cannot refer to the declared variable itself

Voici des exemples de déclarations de variables locales implicitement typées incorrectes :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

La valeur d’une variable locale est obtenue dans une expression à l’aide d’un simple_name (noms simples) et la valeur d’une variable locale est modifiée à l’aide d’une assignation (opérateurs d’affectation).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). Une variable locale doit être assignée définitivement (assignation définie) à chaque emplacement où sa valeur est obtenue.A local variable must be definitely assigned (Definite assignment) at each location where its value is obtained.

La portée d’une variable locale déclarée dans un local_variable_declaration est le bloc dans lequel la déclaration se produit.The scope of a local variable declared in a local_variable_declaration is the block in which the declaration occurs. La référence à une variable locale dans une position textuelle qui précède le local_variable_declarator de la variable locale est une erreur.It is an error to refer to a local variable in a textual position that precedes the local_variable_declarator of the local variable. Dans l’étendue d’une variable locale, il s’agit d’une erreur de compilation pour déclarer une autre constante ou variable locale portant le même nom.Within the scope of a local variable, it is a compile-time error to declare another local variable or constant with the same name.

Une déclaration de variable locale qui déclare plusieurs variables est équivalente à plusieurs déclarations de variables uniques de même type.A local variable declaration that declares multiple variables is equivalent to multiple declarations of single variables with the same type. En outre, un initialiseur de variable dans une déclaration de variable locale correspond exactement à une instruction d’assignation qui est insérée immédiatement après la déclaration.Furthermore, a variable initializer in a local variable declaration corresponds exactly to an assignment statement that is inserted immediately after the declaration.

L’exempleThe example

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

correspond exactement àcorresponds exactly to

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

Dans une déclaration de variable locale implicitement typée, le type de la variable locale déclarée est considéré comme étant le même que le type de l’expression utilisée pour initialiser la variable.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. Exemple :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>();

Les déclarations de variables locales implicitement typées ci-dessus sont équivalentes précisément aux déclarations explicitement typées suivantes :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>();

Déclarations de constantes localesLocal constant declarations

Un local_constant_declaration déclare une ou plusieurs constantes locales.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
    ;

Le type d’un local_constant_declaration spécifie le type des constantes introduites par la déclaration.The type of a local_constant_declaration specifies the type of the constants introduced by the declaration. Le type est suivi d’une liste de constant_declarators, chacun d’entre eux introduisant une nouvelle constante.The type is followed by a list of constant_declarators, each of which introduces a new constant. Un constant_declarator se compose d’un identificateur qui nomme la constante, suivi d’un jeton « = », suivi d’un constant_expression (expressions constantes) qui donne la valeur de la constante.A constant_declarator consists of an identifier that names the constant, followed by an "=" token, followed by a constant_expression (Constant expressions) that gives the value of the constant.

Le type et le constant_expression d’une déclaration de constante locale doivent suivre les mêmes règles que celles d’une déclaration de membre constante (constantes).The type and constant_expression of a local constant declaration must follow the same rules as those of a constant member declaration (Constants).

La valeur d’une constante locale est obtenue dans une expression à l’aide d’un simple_name (noms simples).The value of a local constant is obtained in an expression using a simple_name (Simple names).

La portée d’une constante locale est le bloc dans lequel la déclaration se produit.The scope of a local constant is the block in which the declaration occurs. Il est erroné de faire référence à une constante locale dans une position textuelle qui précède son constant_declarator.It is an error to refer to a local constant in a textual position that precedes its constant_declarator. Dans l’étendue d’une constante locale, il s’agit d’une erreur de compilation pour déclarer une autre constante ou variable locale portant le même nom.Within the scope of a local constant, it is a compile-time error to declare another local variable or constant with the same name.

Une déclaration de constante locale qui déclare plusieurs constantes est équivalente à plusieurs déclarations de constantes uniques avec le même type.A local constant declaration that declares multiple constants is equivalent to multiple declarations of single constants with the same type.

Instructions d’expressionExpression statements

Un expression_statement évalue une expression donnée.An expression_statement evaluates a given expression. La valeur calculée par l’expression, le cas échéant, est ignorée.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
    ;

Toutes les expressions ne sont pas autorisées en tant qu’instructions.Not all expressions are permitted as statements. En particulier, les expressions telles x + y que x == 1 et qui calculent simplement une valeur (qui sera ignorée) ne sont pas autorisées en tant qu’instructions.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’exécution d’un expression_statement évalue l’expression contenue, puis transfère le contrôle au point de terminaison du expression_statement.Execution of an expression_statement evaluates the contained expression and then transfers control to the end point of the expression_statement. Le point de terminaison d’un expression_statement est accessible si ce expression_statement est accessible.The end point of an expression_statement is reachable if that expression_statement is reachable.

Instructions de sélectionSelection statements

Instructions de sélection sélectionnez l’une des nombreuses instructions possibles pour l’exécution en fonction de la valeur d’une expression.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
    ;

L’instruction ifThe if statement

L' if instruction sélectionne une instruction à exécuter en fonction de la valeur d’une expression booléenne.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
    ;

Un else composant est associé au précédent if lexicalement le plus proche qui est autorisé par la syntaxe.An else part is associated with the lexically nearest preceding if that is allowed by the syntax. Ainsi, une if instruction de la formeThus, an if statement of the form

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

est équivalent àis equivalent to

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

Une if instruction est exécutée comme suit :An if statement is executed as follows:

  • L’expression Boolean_expression (expressions booléennes) est évaluée.The boolean_expression (Boolean expressions) is evaluated.
  • Si l’expression booléenne génère true, le contrôle est transféré à la première instruction incorporée.If the boolean expression yields true, control is transferred to the first embedded statement. Quand et si le contrôle atteint le point de terminaison de cette instruction, le contrôle est transféré au point de if terminaison de l’instruction.When and if control reaches the end point of that statement, control is transferred to the end point of the if statement.
  • Si l’expression booléenne génère false et si une else partie est présente, le contrôle est transféré à la deuxième instruction incorporée.If the boolean expression yields false and if an else part is present, control is transferred to the second embedded statement. Quand et si le contrôle atteint le point de terminaison de cette instruction, le contrôle est transféré au point de if terminaison de l’instruction.When and if control reaches the end point of that statement, control is transferred to the end point of the if statement.
  • Si l’expression booléenne génère false et si une else partie n’est pas présente, le contrôle est transféré au point de terminaison de if l’instruction.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 première instruction incorporée d' if une instruction est accessible si l' if instruction est accessible et que l’expression booléenne n’a pas la valeur falsede constante.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 deuxième instruction incorporée d' if une instruction, si elle est présente, est accessible if si l’instruction est accessible et si l’expression booléenne n’a pas la truevaleur de constante.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.

Le point de terminaison d' if une instruction est accessible si le point de terminaison d’au moins une de ses instructions incorporées est accessible.The end point of an if statement is reachable if the end point of at least one of its embedded statements is reachable. En outre, le point de terminaison d' if une instruction else sans partie est accessible si l' if instruction est accessible et que l’expression booléenne n’a pas la valeur truede constante.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.

Instruction switchThe switch statement

L’instruction switch sélectionne pour l’exécution une liste d’instructions ayant une étiquette Switch associée qui correspond à la valeur de l’expression 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 se compose du mot clé switch, suivi d’une expression entre parenthèses (appelée expression de commutateur), suivie d’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 se compose de zéro, un ou plusieurs switch_section, entre accolades.The switch_block consists of zero or more switch_sections, enclosed in braces. Chaque switch_section se compose d’un ou plusieurs switch_label, suivis d’un statement_list (listes d’instructions).Each switch_section consists of one or more switch_labels followed by a statement_list (Statement lists).

Le type gouvernant d’une switch instruction est établi par l’expression de switch.The governing type of a switch statement is established by the switch expression.

  • Si le type de l’expression de commutateur est sbyte, byte, short, ushort, int, uint, long, ulong, bool, char, 0 ou enum_type, ou s’il s’agit du type Nullable correspondant à l’un de ces types , il s’agit du type gouvernant de l’instruction 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.
  • Dans le cas contraire, une seule conversion implicite définie par l’utilisateur (conversions définies par l’utilisateur) doit exister du type de l’expression de commutateur à l’un sbytedes types shortrégis possibles suivants :, byte,, ushort , int, uint, ,long ,char,ou, un type Nullable correspondant à l’un de ces types. 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.
  • Sinon, si aucune conversion implicite n’existe, ou s’il existe plusieurs conversions implicites, une erreur se produit au moment de la compilation.Otherwise, if no such implicit conversion exists, or if more than one such implicit conversion exists, a compile-time error occurs.

L’expression constante de chaque case étiquette doit indiquer une valeur implicitement convertible (conversions implicites) en type gouvernant de l' switch instruction.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. Une erreur de compilation se produit si au moins deux case étiquettes dans la même switch instruction spécifient la même valeur de constante.A compile-time error occurs if two or more case labels in the same switch statement specify the same constant value.

Il peut y avoir au plus default une étiquette dans une instruction switch.There can be at most one default label in a switch statement.

Une switch instruction est exécutée comme suit :A switch statement is executed as follows:

  • L’expression de commutateur est évaluée et convertie en type gouvernant.The switch expression is evaluated and converted to the governing type.
  • Si l’une des constantes spécifiées dans case une étiquette dans la switch même instruction est égale à la valeur de l’expression de commutateur, le contrôle est transféré à la case liste d’instructions à la suite de l’étiquette correspondante.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.
  • Si aucune des constantes spécifiées dans case les étiquettes de la switch même instruction n’est égale à la valeur de l’expression de commutateur, default et si une étiquette est présente, le contrôle est transféré à la default liste d’instructions à la suite du noms.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.
  • Si aucune des constantes spécifiées dans case les étiquettes de la switch même instruction n’est égale à la valeur de l’expression de commutateur, default et si aucune étiquette n’est présente, le contrôle est transféré au switch point de terminaison de l’instruction.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.

Si le point de terminaison de la liste d’instructions d’une section switch est accessible, une erreur de compilation se produit.If the end point of the statement list of a switch section is reachable, a compile-time error occurs. C’est ce que l’on appelle la règle « aucune chute ».This is known as the "no fall through" rule. L’exempleThe example

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

est valide, car aucune section switch n’a un point de terminaison accessible.is valid because no switch section has a reachable end point. Contrairement à C C++et, l’exécution d’une section switch n’est pas autorisée à passer à la section switch suivante, et l’exempleUnlike 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();
}

génère une erreur au moment de la compilation.results in a compile-time error. Lorsque l’exécution d’une section switch doit être suivie par l’exécution d’une autre section switch, goto case une goto default instruction explicite ou doit être utilisée :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;
}

Plusieurs étiquettes sont autorisées dans un switch_section.Multiple labels are permitted in a switch_section. L’exempleThe example

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

est valide.is valid. L’exemple ne viole pas la règle « aucune chute », car les étiquettes case 2: et default: font partie du même 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 règle « aucune chute » empêche une classe courante de bogues qui se produisent dans C C++ et break lorsque les instructions sont omises par inadvertance.The "no fall through" rule prevents a common class of bugs that occur in C and C++ when break statements are accidentally omitted. En outre, en raison de cette règle, les sections Switch d' switch une instruction peuvent être réorganisées arbitrairement sans affecter le comportement de l’instruction.In addition, because of this rule, the switch sections of a switch statement can be arbitrarily rearranged without affecting the behavior of the statement. Par exemple, les sections de l' switch instruction ci-dessus peuvent être inversées sans affecter le comportement de l’instruction :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;
}

La liste d’instructions d’une section switch se termine breakgénéralement goto casepar une goto default instruction,, ou, mais toute construction qui restitue le point de terminaison de la liste d’instructions inaccessible est autorisée.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. Par exemple, une while instruction contrôlée par l’expression true booléenne est connue pour ne jamais atteindre son point de terminaison.For example, a while statement controlled by the boolean expression true is known to never reach its end point. De même, throw une return instruction ou transfère toujours le contrôle ailleurs et n’atteint jamais son point de terminaison.Likewise, a throw or return statement always transfers control elsewhere and never reaches its end point. Ainsi, l’exemple suivant est valide :Thus, the following example is valid:

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

Le type gouvernant d’une switch instruction peut être le type string.The governing type of a switch statement may be the type string. Exemple :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;
    }
}

À l’instar des opérateurs d’égalité de chaînes (opérateurs switch d’égalité dechaînes), l’instruction respecte la casse et exécute une section switch donnée uniquement si la case chaîne d’expression de commutateur correspond exactement à une constante d’étiquette.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.

Lorsque le type gouvernant d’une switch instruction est string, la valeur null est autorisée comme constante d’étiquette case.When the governing type of a switch statement is string, the value null is permitted as a case label constant.

Les statement_lists d’un switch_block peuvent contenir des instructions de déclaration (instructions de déclaration).The statement_lists of a switch_block may contain declaration statements (Declaration statements). La portée d’une variable locale ou d’une constante déclarée dans un bloc switch est le bloc switch.The scope of a local variable or constant declared in a switch block is the switch block.

La liste d’instructions d’une section switch donnée est accessible si l' switch instruction est accessible et qu’au moins l’une des conditions suivantes est vraie :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’expression de commutateur est une valeur non constante.The switch expression is a non-constant value.
  • L’expression de commutateur est une valeur constante qui correspond case à une étiquette dans la section switch.The switch expression is a constant value that matches a case label in the switch section.
  • L’expression de commutateur est une valeur constante qui ne correspond case à aucune étiquette, et la section Switch default contient l’étiquette.The switch expression is a constant value that doesn't match any case label, and the switch section contains the default label.
  • Une étiquette de commutateur de la section switch est référencée par une instruction goto case ou goto default accessible.A switch label of the switch section is referenced by a reachable goto case or goto default statement.

Le point de terminaison d' switch une instruction est accessible si au moins l’une des conditions suivantes est vraie :The end point of a switch statement is reachable if at least one of the following is true:

  • L' switch instruction contient une break instruction accessible qui quitte l' switch instruction.The switch statement contains a reachable break statement that exits the switch statement.
  • L' switch instruction est accessible, l’expression de commutateur est une valeur non constante et aucune default étiquette n’est présente.The switch statement is reachable, the switch expression is a non-constant value, and no default label is present.
  • L' switch instruction est accessible, l’expression de commutateur est une valeur constante qui ne correspond à case aucune étiquette et aucune default étiquette n’est présente.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.

Instructions d’itérationIteration statements

Les instructions d’itération exécutent plusieurs fois une instruction incorporée.Iteration statements repeatedly execute an embedded statement.

iteration_statement
    : while_statement
    | do_statement
    | for_statement
    | foreach_statement
    ;

Instruction whileThe while statement

L' while instruction exécute de manière conditionnelle une instruction incorporée zéro ou plusieurs fois.The while statement conditionally executes an embedded statement zero or more times.

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

Une while instruction est exécutée comme suit :A while statement is executed as follows:

  • L’expression Boolean_expression (expressions booléennes) est évaluée.The boolean_expression (Boolean expressions) is evaluated.
  • Si l’expression booléenne génère true, le contrôle est transféré à l’instruction incorporée.If the boolean expression yields true, control is transferred to the embedded statement. Quand et si le contrôle atteint le point de terminaison de l’instruction incorporée (peut- continue être à partir de l’exécution d’une instruction), while le contrôle est transféré au début de l’instruction.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.
  • Si l’expression booléenne génère false, le contrôle est transféré au point de terminaison de l' while instruction.If the boolean expression yields false, control is transferred to the end point of the while statement.

Dans l’instruction incorporée d' while une instruction, break une instruction (instruction Break) peut être utilisée pour transférer le contrôle au point de terminaison de while l’instruction (terminant ainsi l’itération de l’instruction incorporée) et un continue Statement (instruction continue) peut être utilisé pour transférer le contrôle au point de terminaison de l’instruction incorporée (ce qui effectue une autre while itération de l’instruction).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’instruction incorporée d' while une instruction est accessible si l' while instruction est accessible et que l’expression booléenne n’a pas la valeur falsede constante.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.

Le point de terminaison d' while une instruction est accessible si au moins l’une des conditions suivantes est vraie :The end point of a while statement is reachable if at least one of the following is true:

  • L' while instruction contient une break instruction accessible qui quitte l' while instruction.The while statement contains a reachable break statement that exits the while statement.
  • L' while instruction est accessible et l’expression booléenne n’a pas la valeur truede constante.The while statement is reachable and the boolean expression does not have the constant value true.

Instruction doThe do statement

L' do instruction exécute de manière conditionnelle une instruction incorporée une ou plusieurs fois.The do statement conditionally executes an embedded statement one or more times.

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

Une do instruction est exécutée comme suit :A do statement is executed as follows:

  • Le contrôle est transféré à l’instruction incorporée.Control is transferred to the embedded statement.
  • Quand et si le contrôle atteint le point de terminaison de l’instruction incorporée (peut-être à partir de l’exécution d’une instruction continue), le Boolean_expression (expressions booléennes) est évalué.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. Si l’expression booléenne génère true, le contrôle est transféré au début de l' do instruction.If the boolean expression yields true, control is transferred to the beginning of the do statement. Sinon, le contrôle est transféré au point de terminaison de do l’instruction.Otherwise, control is transferred to the end point of the do statement.

Dans l’instruction incorporée d' do une instruction, break une instruction (instruction Break) peut être utilisée pour transférer le contrôle au point de terminaison de do l’instruction (terminant ainsi l’itération de l’instruction incorporée) et un continue Statement (instruction continue) peut être utilisé pour transférer le contrôle au point de terminaison de l’instruction incorporée.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’instruction incorporée d' do une instruction est accessible si l' do instruction est accessible.The embedded statement of a do statement is reachable if the do statement is reachable.

Le point de terminaison d' do une instruction est accessible si au moins l’une des conditions suivantes est vraie :The end point of a do statement is reachable if at least one of the following is true:

  • L' do instruction contient une break instruction accessible qui quitte l' do instruction.The do statement contains a reachable break statement that exits the do statement.
  • Le point de terminaison de l’instruction incorporée est accessible et l’expression booléenne n’a pas la valeur truede constante.The end point of the embedded statement is reachable and the boolean expression does not have the constant value true.

Instruction forThe for statement

L' for instruction évalue une séquence d’expressions d’initialisation, puis, alors qu’une condition a la valeur true, exécute à plusieurs reprises une instruction incorporée et évalue une séquence d’expressions d’itération.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)*
    ;

Le for_initializer, le cas échéant, se compose soit d’un local_variable_declaration (déclarations de variables locales), soit d’une liste d' statement_expressions (instructions d’expression) séparées par des virgules.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. La portée d’une variable locale déclarée par un for_initializer commence au local_variable_declarator pour la variable et s’étend jusqu’à la fin de l’instruction incorporée.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’étendue comprend for_condition et for_iterator.The scope includes the for_condition and the for_iterator.

Le for_condition, s’il est présent, doit être un Boolean_expression (expressions booléennes).The for_condition, if present, must be a boolean_expression (Boolean expressions).

Le for_iterator, le cas échéant, se compose d’une liste d' statement_expressions (instructions d’expression) séparés par des virgules.The for_iterator, if present, consists of a list of statement_expressions (Expression statements) separated by commas.

Une instruction for est exécutée comme suit :A for statement is executed as follows:

  • Si un for_initializer est présent, les initialiseurs de variable ou les expressions d’instruction sont exécutés dans l’ordre dans lequel ils sont écrits.If a for_initializer is present, the variable initializers or statement expressions are executed in the order they are written. Cette étape n’est effectuée qu’une seule fois.This step is only performed once.
  • Si un for_condition est présent, il est évalué.If a for_condition is present, it is evaluated.
  • Si le for_condition n’est pas présent ou si l’évaluation donne true, le contrôle est transféré à l’instruction incorporée.If the for_condition is not present or if the evaluation yields true, control is transferred to the embedded statement. Quand et si le contrôle atteint le point de terminaison de l’instruction incorporée (peut-être à partir de l’exécution d’une instruction continue), les expressions du for_iterator, le cas échéant, sont évaluées dans l’ordre, puis une autre itération est effectuée, en commençant par évaluation de for_condition dans l’étape ci-dessus.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.
  • Si le for_condition est présent et que l’évaluation produit false, le contrôle est transféré vers le point de terminaison de l’instruction for.If the for_condition is present and the evaluation yields false, control is transferred to the end point of the for statement.

Dans l’instruction incorporée d’une instruction for, une instruction break (l’instruction Break) peut être utilisée pour transférer le contrôle au point de terminaison de l’instruction for (par conséquent, terminer l’itération de l’instruction incorporée) et une instruction continue ( L’instruction continue) peut être utilisée pour transférer le contrôle au point de terminaison de l’instruction incorporée (en exécutant donc le for_iterator et en exécutant une autre itération de l’instruction for, en commençant par 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’instruction incorporée d' for une instruction est accessible si l’une des conditions suivantes est remplie :The embedded statement of a for statement is reachable if one of the following is true:

  • L’instruction for est accessible et aucun for_condition n’est présent.The for statement is reachable and no for_condition is present.
  • L’instruction for est accessible et un for_condition est présent et n’a pas la valeur constante false.The for statement is reachable and a for_condition is present and does not have the constant value false.

Le point de terminaison d' for une instruction est accessible si au moins l’une des conditions suivantes est vraie :The end point of a for statement is reachable if at least one of the following is true:

  • L' for instruction contient une break instruction accessible qui quitte l' for instruction.The for statement contains a reachable break statement that exits the for statement.
  • L’instruction for est accessible et un for_condition est présent et n’a pas la valeur constante true.The for statement is reachable and a for_condition is present and does not have the constant value true.

Instruction foreachThe foreach statement

L' foreach instruction énumère les éléments d’une collection, en exécutant une instruction incorporée pour chaque élément de la collection.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
    ;

Le type et l' identificateur d’une foreach instruction déclarent la variable d’itération de l’instruction.The type and identifier of a foreach statement declare the iteration variable of the statement. Si l’identificateur var est donné en tant que local_variable_type, et qu’aucun type nommé var n’est dans la portée, la variable d’itération est dite une variable d’itération implicitement typéeet son type est considéré comme le type d’élément du foreach comme indiqué ci-dessous.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 variable d’itération correspond à une variable locale en lecture seule avec une portée qui s’étend sur l’instruction incorporée.The iteration variable corresponds to a read-only local variable with a scope that extends over the embedded statement. Pendant l’exécution d' foreach une instruction, la variable d’itération représente l’élément de collection pour lequel une itération est en cours d’exécution.During execution of a foreach statement, the iteration variable represents the collection element for which an iteration is currently being performed. Une erreur de compilation se produit si l’instruction incorporée tente de modifier la variable d’itération (par le ++ biais -- de l’assignation ou des opérateurs et) ou ref de out passer la variable d’itération en tant que paramètre ou.A compile-time error occurs if the embedded statement attempts to modify the iteration variable (via assignment or the ++ and -- operators) or pass the iteration variable as a ref or out parameter.

Dans ce qui suit, par souci de IEnumerableconcision IEnumerable<T> , IEnumerator<T> IEnumerator, et font référence aux types correspondants dans les System.Collections espaces System.Collections.Genericde noms et.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.

Le traitement au moment de la compilation d’une instruction foreach détermine d’abord le type de collection, le type d' énumérateur et le type d’élément de l’expression.The compile-time processing of a foreach statement first determines the collection type, enumerator type and element type of the expression. Cette détermination se déroule comme suit :This determination proceeds as follows:

  • Si le type X d' expression est un type tableau, il existe une X IEnumerable conversion de référence implicite de en interface ( System.Array puisque implémente cette interface).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). Le type de collection est IEnumerable l’interface, le type d’énumérateur IEnumerator est l’interface et le type d’élément est le type d’élément Xdu type tableau.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.

  • Si le type X d' expression est dynamic , il y a IEnumerable une conversion implicite d' expression en interface (conversions dynamiques implicites).If the type X of expression is dynamic then there is an implicit conversion from expression to the IEnumerable interface (Implicit dynamic conversions). Le type de collection est IEnumerable l’interface et le type d’énumérateur IEnumerator est l’interface.The collection type is the IEnumerable interface and the enumerator type is the IEnumerator interface. Si l’identificateur var est fourni en tant que local_variable_type , le type d’élément est dynamic, sinon il est object.If the var identifier is given as the local_variable_type then the element type is dynamic, otherwise it is object.

  • Sinon, déterminez si le X type a une GetEnumerator méthode appropriée :Otherwise, determine whether the type X has an appropriate GetEnumerator method:

    • Effectuez une recherche de membre sur X le type avec GetEnumerator l’identificateur et aucun argument de type.Perform member lookup on the type X with identifier GetEnumerator and no type arguments. Si la recherche de membre ne produit pas de correspondance, si elle génère une ambiguïté ou si elle produit une correspondance qui n’est pas un groupe de méthodes, recherchez une interface énumérable comme décrit ci-dessous.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. Il est recommandé d’émettre un avertissement si la recherche de membres produit tout sauf un groupe de méthodes ou aucune correspondance.It is recommended that a warning be issued if member lookup produces anything except a method group or no match.
    • Exécutez la résolution de surcharge à l’aide du groupe de méthodes résultant et d’une liste d’arguments vide.Perform overload resolution using the resulting method group and an empty argument list. Si la résolution de surcharge entraîne l’absence de méthodes applicables, provoque une ambiguïté ou produit une seule meilleure méthode, mais que cette méthode est statique ou non publique, recherchez une interface énumérable comme décrit ci-dessous.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. Il est recommandé d’émettre un avertissement si la résolution de surcharge produit tout sauf une méthode d’instance publique non ambiguë ou aucune méthode applicable.It is recommended that a warning be issued if overload resolution produces anything except an unambiguous public instance method or no applicable methods.
    • Si le type E de retour de GetEnumerator la méthode n’est pas un type de classe, de struct ou d’interface, une erreur est générée et aucune autre étape n’est prise.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 recherche de membres est E effectuée sur avec l' Current identificateur et aucun argument de type.Member lookup is performed on E with the identifier Current and no type arguments. Si la recherche de membre ne produit aucune correspondance, le résultat est une erreur, ou le résultat est tout sauf une propriété d’instance publique qui autorise la lecture, une erreur est générée et aucune autre étape n’est effectuée.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 recherche de membres est E effectuée sur avec l' MoveNext identificateur et aucun argument de type.Member lookup is performed on E with the identifier MoveNext and no type arguments. Si la recherche de membre ne produit aucune correspondance, le résultat est une erreur, ou le résultat est tout sauf un groupe de méthodes, une erreur est générée et aucune autre étape n’est prise.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 résolution de surcharge est effectuée sur le groupe de méthodes avec une liste d’arguments vide.Overload resolution is performed on the method group with an empty argument list. Si la résolution de surcharge entraîne l’absence de méthodes applicables, entraîne une ambiguïté ou produit une seule meilleure méthode, mais cette méthode est statique ou non publique, ou son type de retour n’est boolpas, une erreur est générée et aucune autre étape n’est prise.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.
    • Le type de collection Xest, le type d' E énumérateur est, et le type d' élément est le Current type de la propriété.The collection type is X, the enumerator type is E, and the element type is the type of the Current property.
  • Sinon, recherchez une interface énumérable :Otherwise, check for an enumerable interface:

    • Si parmi tous les types Ti pour lesquels il existe une conversion implicite X de IEnumerable<Ti>en, il existe un type T unique, T qui n' dynamic est pas et pour l' Ti ensemble de l’autre, il existe un conversion implicite IEnumerable<T> de IEnumerable<Ti>en, le type de collection est l' IEnumerable<T>interface, le type d’énumérateur est IEnumerator<T>l’interface et le type d’élément est 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.
    • Sinon, s’il existe plusieurs types de ce type T, une erreur est générée et aucune autre étape n’est effectuée.Otherwise, if there is more than one such type T, then an error is produced and no further steps are taken.
    • Sinon, s’il existe une conversion implicite X de System.Collections.IEnumerable en interface, le type de collection est cette interface, le type d’énumérateur est l' System.Collections.IEnumeratorinterface et le type d’élément est 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.
    • Dans le cas contraire, une erreur est générée et aucune autre étape n’est prise.Otherwise, an error is produced and no further steps are taken.

Les étapes ci-dessus, en cas de réussite, produisent sans ambiguïté Cun type de E collection, un Ttype d’énumérateur et un type d’élément.The above steps, if successful, unambiguously produce a collection type C, enumerator type E and element type T. Une instruction foreach de la formeA foreach statement of the form

foreach (V v in x) embedded_statement

est ensuite développé pour :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 variable e n’est pas visible ou accessible à l’expression x ou à l’instruction incorporée ou à tout autre code source du programme.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 variable v est en lecture seule dans l’instruction incorporée.The variable v is read-only in the embedded statement. S’il n’existe pas de conversion explicite (conversions explicites) de T (type d’élément) en V (le local_variable_type dans l’instruction foreach), une erreur est générée et aucune autre étape n’est prise.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. Si x a la valeur null, une System.NullReferenceException est levée au moment de l’exécution.If x has the value null, a System.NullReferenceException is thrown at run-time.

Une implémentation est autorisée à implémenter une instruction foreach donnée différemment, par exemple pour des raisons de performances, tant que le comportement est cohérent avec l’expansion ci-dessus.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 position de v à l’intérieur de la boucle while est importante pour la façon dont elle est capturée par toute fonction anonyme se produisant dans le 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.

Exemple :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();

Si v a été déclaré en dehors de la boucle while, il est partagé entre toutes les itérations, et sa valeur après la boucle for est la valeur 13finale,, qui correspond à l’impression f de l’appel.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. Au lieu de cela, étant donné que chaque vitération a sa propre variable f , celle capturée par dans la première itération continue 7à contenir la valeur, qui est celle qui sera imprimée.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. (Remarque : les versions antérieures C# de v ont été déclarées en dehors de la boucle while.)(Note: earlier versions of C# declared v outside of the while loop.)

Le corps du bloc finally est construit selon les étapes suivantes :The body of the finally block is constructed according to the following steps:

  • S’il existe une conversion implicite E de System.IDisposable en interface,If there is an implicit conversion from E to the System.IDisposable interface, then

    • Si E est un type valeur qui n’autorise pas les valeurs NULL, la clause finally est développée avec l’équivalent sémantique de :If E is a non-nullable value type then the finally clause is expanded to the semantic equivalent of:

      finally {
          ((System.IDisposable)e).Dispose();
      }
      
    • Dans le cas contraire, la clause finally est étendue à l’équivalent sémantique de :Otherwise the finally clause is expanded to the semantic equivalent of:

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

    Hormis le E fait que si est un type valeur ou un paramètre de type instancié à un type valeur, le Cast e de System.IDisposable en n’entraîne pas de conversion 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.

  • Sinon, si E est un type sealed, la clause finally est développée en bloc vide :Otherwise, if E is a sealed type, the finally clause is expanded to an empty block:

    finally {
    }
    
  • Dans le cas contraire, la clause finally est développée en :Otherwise, the finally clause is expanded to:

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

    La variable d locale n’est pas visible ou accessible à un code utilisateur.The local variable d is not visible to or accessible to any user code. En particulier, il n’est pas en conflit avec une autre variable dont la portée comprend le bloc finally.In particular, it does not conflict with any other variable whose scope includes the finally block.

L’ordre dans lequel foreach traverse les éléments d’un tableau est le suivant : Pour les tableaux unidimensionnels, les éléments sont parcourus dans un ordre d’index 0 plus important, en Length - 1commençant par l’index et en terminant par l’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. Pour les tableaux multidimensionnels, les éléments sont parcourus de telle sorte que les index de la dimension la plus à droite soient augmentés en premier, puis la dimension gauche suivante, et ainsi de suite vers la gauche.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.

L’exemple suivant imprime chaque valeur dans un tableau à deux dimensions, dans l’ordre des éléments :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();
    }
}

La sortie produite est la suivante :The output produced is as follows:

1.2 2.3 3.4 4.5 5.6 6.7 7.8 8.9

Dans l’exempleIn the example

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

le type de n est déduit comme étant int, le type d’élément de numbers.the type of n is inferred to be int, the element type of numbers.

Instructions de sautJump statements

Les instructions de saut transfèrent le contrôle de manière inconditionnelle.Jump statements unconditionally transfer control.

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

L’emplacement vers lequel une instruction de saut transfère le contrôle est appelé la cible de l’instruction de saut.The location to which a jump statement transfers control is called the target of the jump statement.

Lorsqu’une instruction de saut se produit dans un bloc et que la cible de cette instruction de saut est en dehors de ce bloc, l’instruction de saut est dite pour quitter le bloc.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. Alors qu’une instruction de saut peut transférer le contrôle hors d’un bloc, elle ne peut jamais transférer le contrôle dans un bloc.While a jump statement may transfer control out of a block, it can never transfer control into a block.

L’exécution d’instructions de saut est compliquée par la présence try d’instructions intermédiaires.Execution of jump statements is complicated by the presence of intervening try statements. En l’absence de ces try instructions, une instruction de saut transfère de manière inconditionnelle le contrôle de l’instruction de saut à sa cible.In the absence of such try statements, a jump statement unconditionally transfers control from the jump statement to its target. En présence de ces try instructions intervenues, l’exécution est plus complexe.In the presence of such intervening try statements, execution is more complex. Si l’instruction de saut quitte un ou plusieurs try blocs avec des finally blocs associés, le contrôle finally est initialement transféré au bloc de l' try instruction la plus profonde.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. Quand et si le contrôle atteint le point de terminaison finally d’un bloc, le contrôle est finally transféré au bloc de l’instruction try englobante suivante.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. Ce processus est répété jusqu’à finally ce que les blocs de try toutes les instructions intermédiaires aient été exécutés.This process is repeated until the finally blocks of all intervening try statements have been executed.

Dans l’exempleIn 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");
    }
}

les finally blocs associés à deux try instructions sont exécutés avant que le contrôle soit transféré à la cible de l’instruction de saut.the finally blocks associated with two try statements are executed before control is transferred to the target of the jump statement.

La sortie produite est la suivante :The output produced is as follows:

Before break
Innermost finally block
Outermost finally block
After break

Instruction BreakThe break statement

L' break instruction quitte l’instruction,,, ou switch for while doenglobantela plusprocheforeach .The break statement exits the nearest enclosing switch, while, do, for, or foreach statement.

break_statement
    : 'break' ';'
    ;

La cible d’une break instruction est le point de terminaison de l’instruction, while, switch do for, ou foreach englobante la plus proche.The target of a break statement is the end point of the nearest enclosing switch, while, do, for, or foreach statement. Si une break instruction n’est pas entourée whiled' doune for switchinstruction, foreach ,, ou, une erreur de compilation se produit.If a break statement is not enclosed by a switch, while, do, for, or foreach statement, a compile-time error occurs.

Lorsque plusieurs switchinstructions while, do, break ,, ouforeach sont imbriquées les unes dans les autres, une instruction s’applique uniquement à l’instruction la plus profonde. forWhen multiple switch, while, do, for, or foreach statements are nested within each other, a break statement applies only to the innermost statement. Pour transférer le contrôle entre plusieurs niveaux d’imbrication, goto une instruction (instruction goto) doit être utilisée.To transfer control across multiple nesting levels, a goto statement (The goto statement) must be used.

Une break instruction ne peut pas finally quitter un bloc (instruction try).A break statement cannot exit a finally block (The try statement). Lorsqu’une break instruction se produit dans finally un bloc, la cible de break l’instruction doit se trouver dans finally le même bloc ; sinon, une erreur de compilation se produit.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.

Une break instruction est exécutée comme suit :A break statement is executed as follows:

  • Si l' break instruction quitte un ou plusieurs try blocs avec des finally blocs finally associés, le contrôle est initialement transféré au bloc de l’instruction try la plus profonde.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. Quand et si le contrôle atteint le point de terminaison finally d’un bloc, le contrôle est finally transféré au bloc de l’instruction try englobante suivante.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. Ce processus est répété jusqu’à finally ce que les blocs de try toutes les instructions intermédiaires aient été exécutés.This process is repeated until the finally blocks of all intervening try statements have been executed.
  • Le contrôle est transféré à la cible de break l’instruction.Control is transferred to the target of the break statement.

Étant donné break qu’une instruction transfère sans condition le contrôle ailleurs, le point de break terminaison d’une instruction n’est jamais accessible.Because a break statement unconditionally transfers control elsewhere, the end point of a break statement is never reachable.

Instruction continueThe continue statement

L' continue instruction démarre une nouvelle itération de l’instruction do,, forou while foreach englobante la plus proche.The continue statement starts a new iteration of the nearest enclosing while, do, for, or foreach statement.

continue_statement
    : 'continue' ';'
    ;

La cible d’une continue instruction est le point de terminaison de l’instruction incorporée de l’instruction englobante do, for, ou foreach englobante whilela plus proche.The target of a continue statement is the end point of the embedded statement of the nearest enclosing while, do, for, or foreach statement. Si une continue instruction n’est pas entourée dod' forune whileinstruction foreach ,, ou, une erreur de compilation se produit.If a continue statement is not enclosed by a while, do, for, or foreach statement, a compile-time error occurs.

Lorsque plusieurs whileinstructions do, for,, foreach ou sont imbriquées les unes dans les autres continue , une instruction s’applique uniquement à l’instruction la plus profonde.When multiple while, do, for, or foreach statements are nested within each other, a continue statement applies only to the innermost statement. Pour transférer le contrôle entre plusieurs niveaux d’imbrication, goto une instruction (instruction goto) doit être utilisée.To transfer control across multiple nesting levels, a goto statement (The goto statement) must be used.

Une continue instruction ne peut pas finally quitter un bloc (instruction try).A continue statement cannot exit a finally block (The try statement). Lorsqu’une continue instruction se produit dans finally un bloc, la cible de continue l’instruction doit se trouver dans finally le même bloc ; sinon, une erreur de compilation se produit.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.

Une continue instruction est exécutée comme suit :A continue statement is executed as follows:

  • Si l' continue instruction quitte un ou plusieurs try blocs avec des finally blocs finally associés, le contrôle est initialement transféré au bloc de l’instruction try la plus profonde.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. Quand et si le contrôle atteint le point de terminaison finally d’un bloc, le contrôle est finally transféré au bloc de l’instruction try englobante suivante.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. Ce processus est répété jusqu’à finally ce que les blocs de try toutes les instructions intermédiaires aient été exécutés.This process is repeated until the finally blocks of all intervening try statements have been executed.
  • Le contrôle est transféré à la cible de continue l’instruction.Control is transferred to the target of the continue statement.

Étant donné continue qu’une instruction transfère sans condition le contrôle ailleurs, le point de continue terminaison d’une instruction n’est jamais accessible.Because a continue statement unconditionally transfers control elsewhere, the end point of a continue statement is never reachable.

Instruction gotoThe goto statement

L' goto instruction transfère le contrôle à une instruction qui est marquée par une étiquette.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 cible d’une goto instruction d' identificateur est l’instruction étiquetée avec l’étiquette donnée.The target of a goto identifier statement is the labeled statement with the given label. Si une étiquette portant le nom spécifié n’existe pas dans le membre de fonction actuel, ou si goto l’instruction n’est pas dans la portée de l’étiquette, une erreur de compilation se produit.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. Cette règle autorise l’utilisation d’une goto instruction pour transférer le contrôle hors d’une portée imbriquée, mais pas dans une portée imbriquée.This rule permits the use of a goto statement to transfer control out of a nested scope, but not into a nested scope. Dans l’exempleIn 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);
        }
    }
}

une goto instruction est utilisée pour transférer le contrôle hors d’une portée imbriquée.a goto statement is used to transfer control out of a nested scope.

La cible d’une goto case instruction est la liste d’instructions dans l’instruction immédiatement switch englobante (l’instruction switch), qui contient case une étiquette avec la valeur de constante donnée.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. Si l’instruction goto case n’est pas entourée d’une instruction switch, si le constant_expression n’est pas implicitement convertible (conversion implicite) en type gouvernant de l’instruction switch englobante la plus proche, ou si le le plus proche englobant l’instruction switch ne contient pas d’étiquette case avec la valeur de constante donnée, une erreur de compilation se produit.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 cible d’une goto default instruction est la liste d’instructions dans l’instruction immédiatement switch englobante (l’instruction switch), qui contient default une étiquette.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. Si l' goto default instruction n’est pas entourée d’une switch instruction, ou si l’instruction switch englobante la plus proche default ne contient pas d’étiquette, une erreur de compilation se produit.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.

Une goto instruction ne peut pas finally quitter un bloc (instruction try).A goto statement cannot exit a finally block (The try statement). Lorsqu’une goto instruction se produit dans finally un bloc, la cible de goto l’instruction doit se trouver dans finally le même bloc, sinon une erreur de compilation se produit.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.

Une goto instruction est exécutée comme suit :A goto statement is executed as follows:

  • Si l' goto instruction quitte un ou plusieurs try blocs avec des finally blocs finally associés, le contrôle est initialement transféré au bloc de l’instruction try la plus profonde.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. Quand et si le contrôle atteint le point de terminaison finally d’un bloc, le contrôle est finally transféré au bloc de l’instruction try englobante suivante.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. Ce processus est répété jusqu’à finally ce que les blocs de try toutes les instructions intermédiaires aient été exécutés.This process is repeated until the finally blocks of all intervening try statements have been executed.
  • Le contrôle est transféré à la cible de goto l’instruction.Control is transferred to the target of the goto statement.

Étant donné goto qu’une instruction transfère sans condition le contrôle ailleurs, le point de goto terminaison d’une instruction n’est jamais accessible.Because a goto statement unconditionally transfers control elsewhere, the end point of a goto statement is never reachable.

Instruction returnThe return statement

L' return instruction retourne le contrôle à l’appelant actuel de la fonction dans laquelle return l’instruction apparaît.The return statement returns control to the current caller of the function in which the return statement appears.

return_statement
    : 'return' expression? ';'
    ;

Une return instruction sans expression ne peut être utilisée que dans un membre de fonction qui ne calcule pas de valeur, autrement dit, une méthode avec le type de résultat (corps voiddeméthode), l' set accesseur d’une propriété ou add d’un indexeur, le les remove accesseurs et d’un événement, un constructeur d’instance, un constructeur statique ou un destructeur.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.

Une return instruction avec une expression ne peut être utilisée que dans un membre de fonction qui calcule une valeur, autrement dit, une méthode avec un type de résultat non void get , l’accesseur d’une propriété ou un indexeur ou un opérateur défini par l’utilisateur.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. Une conversion implicite (conversions implicites) doit exister du type de l’expression vers le type de retour de la fonction membre conteneur.An implicit conversion (Implicit conversions) must exist from the type of the expression to the return type of the containing function member.

Les instructions Return peuvent également être utilisées dans le corps d’expressions de fonction anonymes (expressions de fonction anonymes) et participer à la détermination des conversions qui existent pour ces fonctions.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.

Il s’agit d’une erreur de compilation pour return qu’une instruction apparaisse finally dans un bloc (instruction try).It is a compile-time error for a return statement to appear in a finally block (The try statement).

Une return instruction est exécutée comme suit :A return statement is executed as follows:

  • Si l' return instruction spécifie une expression, l’expression est évaluée et la valeur résultante est convertie dans le type de retour de la fonction conteneur par une conversion implicite.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. Le résultat de la conversion devient la valeur de résultat produite par la fonction.The result of the conversion becomes the result value produced by the function.
  • Si l' return instruction est entourée d’un try ou catch de plusieurs blocs finally ou avec des blocs associés, le contrôle finally est initialement transféré au try bloc de l’instruction la plus profonde.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. Quand et si le contrôle atteint le point de terminaison finally d’un bloc, le contrôle est finally transféré au bloc de l’instruction try englobante suivante.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. Ce processus est répété jusqu’à finally ce que les blocs de try toutes les instructions englobantes aient été exécutés.This process is repeated until the finally blocks of all enclosing try statements have been executed.
  • Si la fonction conteneur n’est pas une fonction Async, le contrôle est retourné à l’appelant de la fonction conteneur avec la valeur de résultat, le cas échéant.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.
  • Si la fonction conteneur est une fonction Async, le contrôle est retourné à l’appelant actuel et la valeur de résultat, le cas échéant, est enregistrée dans la tâche de retour, comme décrit dans (interfaces d’énumération).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).

Étant donné return qu’une instruction transfère sans condition le contrôle ailleurs, le point de return terminaison d’une instruction n’est jamais accessible.Because a return statement unconditionally transfers control elsewhere, the end point of a return statement is never reachable.

Instruction throwThe throw statement

L' throw instruction lève une exception.The throw statement throws an exception.

throw_statement
    : 'throw' expression? ';'
    ;

Une throw instruction avec une expression génère la valeur produite par l’évaluation de l’expression.A throw statement with an expression throws the value produced by evaluating the expression. L’expression doit indiquer une valeur du type System.Exceptionde classe, d’un type de classe qui dérive de System.Exception ou d’un type de paramètre de System.Exception type ayant (ou une sous-classe) comme classe de base effective.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. Si l’évaluation de l’expression nullproduit, System.NullReferenceException une exception est levée à la place.If evaluation of the expression produces null, a System.NullReferenceException is thrown instead.

Une throw instruction sans expression ne peut être utilisée que dans un catch bloc, auquel cas cette instruction lève à nouveau l’exception qui est actuellement gérée par ce catch bloc.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.

Étant donné throw qu’une instruction transfère sans condition le contrôle ailleurs, le point de throw terminaison d’une instruction n’est jamais accessible.Because a throw statement unconditionally transfers control elsewhere, the end point of a throw statement is never reachable.

Quand une exception est levée, le contrôle est transféré à la catch première clause dans une instruction try englobante qui peut gérer l’exception.When an exception is thrown, control is transferred to the first catch clause in an enclosing try statement that can handle the exception. Le processus qui a lieu à partir du point de l’exception levée jusqu’au point de transfert du contrôle à un gestionnaire d’exceptions approprié est appelé propagation des exceptions.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 propagation d’une exception consiste à évaluer à plusieurs reprises les étapes suivantes jusqu' catch à ce qu’une clause qui corresponde à l’exception soit trouvée.Propagation of an exception consists of repeatedly evaluating the following steps until a catch clause that matches the exception is found. Dans cette description, le point de levée est initialement l’emplacement où l’exception est levée.In this description, the throw point is initially the location at which the exception is thrown.

  • Dans le membre de fonction actuel, try chaque instruction qui encadre le point d’exception est examinée.In the current function member, each try statement that encloses the throw point is examined. Pour chaque instruction S, en commençant par l' try instruction la plus profonde et en try terminant par l’instruction la plus extérieure, les étapes suivantes sont évaluées :For each statement S, starting with the innermost try statement and ending with the outermost try statement, the following steps are evaluated:

    • Si le try bloc de S encadre le point de levée et si S a une ou plusieurs catch clauses, les catch clauses sont examinées par ordre d’apparition pour trouver un gestionnaire approprié pour l’exception, conformément aux règles spécifiées dans Section de l’instruction 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. Si une clause catch correspondante est trouvée, la propagation de l’exception est terminée en transférant le contrôle au bloc catch de cette clause.If a matching catch clause is located, the exception propagation is completed by transferring control to the block of that catch clause.

    • Sinon, si le try bloc ou un catch bloc de S englobe le point de levée et si S a un finally bloc, le contrôle est transféré au finally bloc.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. Si le finally bloc lève une autre exception, le traitement de l’exception actuelle est terminé.If the finally block throws another exception, processing of the current exception is terminated. Dans le cas contraire, lorsque le contrôle atteint le finally point de terminaison du bloc, le traitement de l’exception actuelle est poursuivi.Otherwise, when control reaches the end point of the finally block, processing of the current exception is continued.

  • Si un gestionnaire d’exceptions n’a pas été trouvé dans l’appel de la fonction en cours, l’appel de la fonction se termine et l’un des éléments suivants se produit :If an exception handler was not located in the current function invocation, the function invocation is terminated, and one of the following occurs:

    • Si la fonction active est non Async, les étapes ci-dessus sont répétées pour l’appelant de la fonction avec un point d’exception correspondant à l’instruction à partir de laquelle la fonction membre a été appelée.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.

    • Si la fonction active est Async et retourne une tâche, l’exception est enregistrée dans la tâche de retour, qui est placée dans un état Faulted ou Cancelled, comme décrit dans interfaces d’énumérateur.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.

    • Si la fonction active est Async et void-retournant, le contexte de synchronisation du thread actuel est notifié comme décrit dans interfaces Enumerable.If the current function is async and void-returning, the synchronization context of the current thread is notified as described in Enumerable interfaces.

  • Si le traitement des exceptions met fin à tous les appels de membre de fonction dans le thread actuel, ce qui indique que le thread n’a aucun gestionnaire pour l’exception, le thread se termine lui-même.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’impact d’une telle terminaison est défini par l’implémentation.The impact of such termination is implementation-defined.

Instruction tryThe try statement

L' try instruction fournit un mécanisme permettant d’intercepter les exceptions qui se produisent pendant l’exécution d’un bloc.The try statement provides a mechanism for catching exceptions that occur during execution of a block. En outre, try l’instruction offre la possibilité de spécifier un bloc de code qui est toujours exécuté lorsque le contrôle try quitte l’instruction.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
    ;

Il existe trois formes d' try instructions possibles :There are three possible forms of try statements:

  • Bloc suivi d’un ou de plusieurs catch blocs. tryA try block followed by one or more catch blocks.
  • Bloc suivi d’un finally bloc. tryA try block followed by a finally block.
  • Bloc suivi d’un ou de plusieurs catch blocs suivis d' finally un bloc. tryA try block followed by one or more catch blocks followed by a finally block.

Quand une clause catch spécifie un exception_specifier, le type doit être System.Exception, un type qui dérive de System.Exception ou un type de paramètre de type qui a System.Exception (ou une sous-classe de ce type) comme classe de base effective.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.

Quand une clause catch spécifie à la fois un exception_specifier avec un identificateur, une variable d’exception du nom et du type donnés est déclarée.When a catch clause specifies both an exception_specifier with an identifier, an exception variable of the given name and type is declared. La variable d’exception correspond à une variable locale avec une étendue qui s’étend catch sur la clause.The exception variable corresponds to a local variable with a scope that extends over the catch clause. Pendant l’exécution du exception_filter et du bloc, la variable d’exception représente l’exception actuellement gérée.During execution of the exception_filter and block, the exception variable represents the exception currently being handled. À des fins de vérification de l’attribution définie, la variable d’exception est considérée comme assignée de manière définitive dans toute son étendue.For purposes of definite assignment checking, the exception variable is considered definitely assigned in its entire scope.

À moins catch qu’une clause comprenne un nom de variable d’exception, il est impossible d’accéder à l’objet catch d’exception dans le filtre et le bloc.Unless a catch clause includes an exception variable name, it is impossible to access the exception object in the filter and catch block.

Une clause catch qui ne spécifie pas de exception_specifier est appelée clause générale catch.A catch clause that does not specify an exception_specifier is called a general catch clause.

Certains langages de programmation peuvent prendre en charge des exceptions qui ne peuvent pas être représentées en tant qu’objet dérivé de System.Exception, bien que ces exceptions ne puissent jamais être générées par C# le code.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. Une clause catch générale peut être utilisée pour intercepter ces exceptions.A general catch clause may be used to catch such exceptions. Par conséquent, une catch clause générale est sémantiquement différente d’une clause qui spécifie le type System.Exception, dans le cas où la première peut également intercepter des exceptions d’autres langages.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.

Afin de localiser un gestionnaire pour une exception, catch les clauses sont examinées dans l’ordre lexical.In order to locate a handler for an exception, catch clauses are examined in lexical order. Si une catch clause spécifie un type mais aucun filtre d’exception, il s’agit d’une erreur de compilation catch pour une clause ultérieure try dans la même instruction pour spécifier un type qui est le même que, ou qui est dérivé de ce type.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. Si une catch clause ne spécifie aucun type et aucun filtre, il doit s' catch agir de la try dernière clause pour cette instruction.If a catch clause specifies no type and no filter, it must be the last catch clause for that try statement.

Dans un catch bloc, une throw instruction (instruction throw) sans expression peut être utilisée pour lever à nouveau l’exception interceptée par le catch bloc.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. Les assignations à une variable d’exception ne modifient pas l’exception qui est levée une nouvelle fois.Assignments to an exception variable do not alter the exception that is re-thrown.

Dans l’exempleIn 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);
        }
    }
}

la méthode F intercepte une exception, écrit des informations de diagnostic dans la console, modifie la variable d’exception et lève à nouveau l’exception.the method F catches an exception, writes some diagnostic information to the console, alters the exception variable, and re-throws the exception. L’exception qui est levée une nouvelle fois est l’exception d’origine, de sorte que la sortie produite est :The exception that is re-thrown is the original exception, so the output produced is:

Exception in F: G
Exception in Main: G

Si le premier bloc catch avait été e levé au lieu de lever à nouveau l’exception actuelle, la sortie produite serait la suivante :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

Il s’agit d’une erreur de compilation pour breakune continueinstruction, goto ou pour transférer le contrôle hors d' finally un bloc.It is a compile-time error for a break, continue, or goto statement to transfer control out of a finally block. Quand une breakinstruction continue, ou goto se trouve dans un finally bloc, la cible de l’instruction doit se trouver dans le finally même bloc, sinon une erreur de compilation se produit.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.

Il s’agit d’une erreur de compilation pour return qu’une instruction se produise dans un finally bloc.It is a compile-time error for a return statement to occur in a finally block.

Une try instruction est exécutée comme suit :A try statement is executed as follows:

  • Le try contrôle est transféré au bloc.Control is transferred to the try block.

  • Quand et si le contrôle atteint le point de terminaison try du bloc :When and if control reaches the end point of the try block:

    • Si l' try instruction contient un finally bloc, le finally bloc est exécuté.If the try statement has a finally block, the finally block is executed.
    • Le contrôle est transféré au point de terminaison de try l’instruction.Control is transferred to the end point of the try statement.
  • Si une exception est propagée à l' try instruction pendant l’exécution try du bloc :If an exception is propagated to the try statement during execution of the try block:

    • Les catch clauses, le cas échéant, sont examinées par ordre d’apparition pour trouver un gestionnaire approprié pour l’exception.The catch clauses, if any, are examined in order of appearance to locate a suitable handler for the exception. Si une catch clause ne spécifie pas de type, ou spécifie le type d’exception ou un type de base du type d’exception :If a catch clause does not specify a type, or specifies the exception type or a base type of the exception type:
      • Si la catch clause déclare une variable d’exception, l’objet exception est assigné à la variable d’exception.If the catch clause declares an exception variable, the exception object is assigned to the exception variable.
      • Si la catch clause déclare un filtre d’exception, le filtre est évalué.If the catch clause declares an exception filter, the filter is evaluated. Si la valeur falseest, la clause catch n’est pas une correspondance, et la recherche se poursuit à travers catch toutes les clauses suivantes pour un gestionnaire approprié.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.
      • Dans le cas catch contraire, la clause est considérée comme une correspondance et le contrôle est catch transféré au bloc correspondant.Otherwise, the catch clause is considered a match, and control is transferred to the matching catch block.
      • Quand et si le contrôle atteint le point de terminaison catch du bloc :When and if control reaches the end point of the catch block:
        • Si l' try instruction contient un finally bloc, le finally bloc est exécuté.If the try statement has a finally block, the finally block is executed.
        • Le contrôle est transféré au point de terminaison de try l’instruction.Control is transferred to the end point of the try statement.
      • Si une exception est propagée à l' try instruction pendant l’exécution catch du bloc :If an exception is propagated to the try statement during execution of the catch block:
        • Si l' try instruction contient un finally bloc, le finally bloc est exécuté.If the try statement has a finally block, the finally block is executed.
        • L’exception est propagée à l’instruction englobante try suivante.The exception is propagated to the next enclosing try statement.
    • Si l' try instruction n’a catch pas de clauses ou catch si aucune clause ne correspond à l’exception :If the try statement has no catch clauses or if no catch clause matches the exception:
      • Si l' try instruction contient un finally bloc, le finally bloc est exécuté.If the try statement has a finally block, the finally block is executed.
      • L’exception est propagée à l’instruction englobante try suivante.The exception is propagated to the next enclosing try statement.

Les instructions d’un finally bloc sont toujours exécutées lorsque le contrôle try quitte une instruction.The statements of a finally block are always executed when control leaves a try statement. Cela est vrai que le transfert de contrôle se produit suite à une exécution normale, en raison de l’exécution d' breakune continueinstruction goto,, return ou, ou suite à la try propagation d’une exception à partir de gestion.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.

Si une exception est levée pendant l’exécution d' finally un bloc et n’est pas interceptée dans le même bloc finally, l’exception est propagée à l' try instruction englobante suivante.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. Si une autre exception était en cours de propagation, cette exception est perdue.If another exception was in the process of being propagated, that exception is lost. Le processus de propagation d’une exception est abordé plus en détail dans la description throw de l’instruction (instruction throw).The process of propagating an exception is discussed further in the description of the throw statement (The throw statement).

Le try bloc d’une try instruction est accessible si l' try instruction est accessible.The try block of a try statement is reachable if the try statement is reachable.

Un catch bloc try d’instruction est accessible si l’instruction est accessible. tryA catch block of a try statement is reachable if the try statement is reachable.

Le finally bloc d’une try instruction est accessible si l' try instruction est accessible.The finally block of a try statement is reachable if the try statement is reachable.

Le point de terminaison d' try une instruction est accessible si les deux conditions suivantes sont remplies :The end point of a try statement is reachable if both of the following are true:

  • Le point de terminaison du try bloc est accessible ou le point de terminaison d’au moins un catch bloc est accessible.The end point of the try block is reachable or the end point of at least one catch block is reachable.
  • Si un finally bloc est présent, le point finally de terminaison du bloc est accessible.If a finally block is present, the end point of the finally block is reachable.

Instructions cochées et non vérifiéesThe checked and unchecked statements

Les checked instructions unchecked et sont utilisées pour contrôler le contexte de contrôle de dépassement de capacité pour les opérations arithmétiques de type intégral et les conversions.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 instruction entraîne l’évaluation de toutes les expressions du bloc dans un contexte vérifié, et l' unchecked instruction entraîne l’évaluation de toutes les expressions du bloc dans un contexte non vérifié.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.

Les checked instructions unchecked etchecked sont équivalentes de manière précise unchecked aux opérateurs et (opérateurs vérifiés etnon vérifiés), sauf qu’ils opèrent sur des blocs au lieu d’expressions.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.

Instruction lockThe lock statement

L' lock instruction obtient le verrou d’exclusion mutuelle pour un objet donné, exécute une instruction, puis libère le verrou.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’expression d’une instruction lock doit désigner une valeur d’un type connu comme étant un reference_type.The expression of a lock statement must denote a value of a type known to be a reference_type. Aucune conversion boxing implicite (conversions boxing) n’est jamais effectuée pour l’expression d’une instruction lock. par conséquent, il s’agit d’une erreur au moment de la compilation pour que l’expression désigne une valeur d’un 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.

Une lock déclaration de la formeA lock statement of the form

lock (x) ...

x est une expression d’un reference_type, est exactement équivalent àwhere 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);
}

sauf que x n’est évalué qu’une seule fois.except that x is only evaluated once.

Lorsqu’un verrou d’exclusion mutuelle est maintenu, le code qui s’exécute dans le même thread d’exécution peut également obtenir et libérer le verrou.While a mutual-exclusion lock is held, code executing in the same execution thread can also obtain and release the lock. Toutefois, le code qui s’exécute dans d’autres threads ne peut pas obtenir le verrou tant que le verrou n’est pas libéré.However, code executing in other threads is blocked from obtaining the lock until the lock is released.

Le System.Type verrouillage des objets pour synchroniser l’accès aux données statiques n’est pas recommandé.Locking System.Type objects in order to synchronize access to static data is not recommended. Un autre code peut verrouiller le même type, ce qui peut entraîner un interblocage.Other code might lock on the same type, which can result in deadlock. Une meilleure approche consiste à synchroniser l’accès aux données statiques en verrouillant un objet statique privé.A better approach is to synchronize access to static data by locking a private static object. Exemple :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) {
            ...
        }
    }
}

Instruction usingThe using statement

L' using instruction obtient une ou plusieurs ressources, exécute une instruction, puis libère la ressource.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
    ;

Une ressource est une classe ou un struct qui implémente System.IDisposable, qui comprend une méthode unique sans paramètre nommée. DisposeA resource is a class or struct that implements System.IDisposable, which includes a single parameterless method named Dispose. Le code qui utilise une ressource peut appeler Dispose pour indiquer que la ressource n’est plus nécessaire.Code that is using a resource can call Dispose to indicate that the resource is no longer needed. Si Dispose n’est pas appelé, la suppression automatique finit par se produire à la suite de garbage collection.If Dispose is not called, then automatic disposal eventually occurs as a consequence of garbage collection.

Si la forme de resource_acquisition est local_variable_declaration , le type de local_variable_declaration doit être dynamic ou un type qui peut être implicitement converti en 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. Si la forme de resource_acquisition est expression , cette expression doit être implicitement convertible en System.IDisposable.If the form of resource_acquisition is expression then this expression must be implicitly convertible to System.IDisposable.

Les variables locales déclarées dans un resource_acquisition sont en lecture seule et doivent inclure un initialiseur.Local variables declared in a resource_acquisition are read-only, and must include an initializer. Une erreur de compilation se produit si l’instruction incorporée tente de modifier ces variables locales (par le biais ++ de -- l’assignation ou des opérateurs et), d’en prendre l’adresse ref ou out de les passer en tant que paramètres ou.A compile-time error occurs if the embedded statement attempts to modify these local variables (via assignment or the ++ and -- operators) , take the address of them, or pass them as ref or out parameters.

Une using instruction est traduite en trois parties : l’acquisition, l’utilisation et la suppression.A using statement is translated into three parts: acquisition, usage, and disposal. L’utilisation de la ressource est implicitement incluse dans try une instruction qui comprend finally une clause.Usage of the resource is implicitly enclosed in a try statement that includes a finally clause. Cette finally clause supprime la ressource.This finally clause disposes of the resource. Si une null ressource est acquise, aucun appel à Dispose n’est effectué et aucune exception n’est levée.If a null resource is acquired, then no call to Dispose is made, and no exception is thrown. Si la ressource est de type dynamic , elle est convertie dynamiquement via une conversion dynamique implicite (conversions dynamiques implicites) IDisposable en lors de l’acquisition afin de garantir la réussite de la conversion avant l’utilisation et Evacuation.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.

Une using déclaration de la formeA using statement of the form

using (ResourceType resource = expression) statement

correspond à l’une des trois expansions possibles.corresponds to one of three possible expansions. Lorsque ResourceType est un type valeur qui n’autorise pas les valeurs NULL, l’expansion estWhen ResourceType is a non-nullable value type, the expansion is

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

Dans le cas ResourceType contraire, quand est un type valeur Nullable ou un type dynamicréférence autre que, le développement estOtherwise, 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();
    }
}

Dans le cas ResourceType contraire dynamic, lorsque est, l’expansion estOtherwise, when ResourceType is dynamic, the expansion is

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

Dans les deux expansions resource , la variable est en lecture seule dans l’instruction incorporée d , et la variable est inaccessible dans, et invisible à, l’instruction incorporée.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.

Une implémentation de est autorisée à implémenter une instruction using donnée différemment, par exemple pour des raisons de performances, tant que le comportement est cohérent avec l’expansion ci-dessus.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.

Une using déclaration de la formeA using statement of the form

using (expression) statement

a les mêmes trois expansions possibles.has the same three possible expansions. Dans ce cas ResourceType , est implicitement le type au moment de la expressioncompilation du, s’il en a un.In this case ResourceType is implicitly the compile-time type of the expression, if it has one. Dans le cas IDisposable contraire, l’interface elle-même est utilisée comme. ResourceTypeOtherwise the interface IDisposable itself is used as the ResourceType. La resource variable est inaccessible dans, et invisible à, l’instruction incorporée.The resource variable is inaccessible in, and invisible to, the embedded statement.

Quand un resource_acquisition prend la forme d’un local_variable_declaration, il est possible d’acquérir plusieurs ressources d’un type donné.When a resource_acquisition takes the form of a local_variable_declaration, it is possible to acquire multiple resources of a given type. Une using déclaration de la formeA using statement of the form

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

équivaut précisément à une séquence d' using instructions imbriquées :is precisely equivalent to a sequence of nested using statements:

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

L’exemple ci-dessous crée un log.txt fichier nommé et écrit deux lignes de texte dans le fichier.The example below creates a file named log.txt and writes two lines of text to the file. L’exemple ouvre ensuite le même fichier pour la lecture et copie les lignes de texte contenues dans la 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);
            }

        }
    }
}

Étant donné TextWriter que TextReader les classes et IDisposable implémentent l’interface, l' using exemple peut utiliser des instructions pour s’assurer que le fichier sous-jacent est correctement fermé après les opérations d’écriture ou de lecture.Since the TextWriter and TextReader classes implement the IDisposable interface, the example can use using statements to ensure that the underlying file is properly closed following the write or read operations.

Instruction yieldThe yield statement

L' yield instruction est utilisée dans un bloc itérateur (blocs) pour produire une valeur à l’objet énumérateur (objets énumérateur) ou à un objet énumérable (objets énumérables) d’un itérateur ou pour signaler la fin de l’itération.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' ';'
    ;

yieldn’est pas un mot réservé ; Il a une signification spéciale uniquement lorsqu’il est utilisé return juste break avant un mot clé ou.yield is not a reserved word; it has special meaning only when used immediately before a return or break keyword. Dans d’autres contextes yield , peut être utilisé comme identificateur.In other contexts, yield can be used as an identifier.

Il existe plusieurs restrictions sur l’emplacement yield où une instruction peut apparaître, comme décrit dans l’exemple suivant.There are several restrictions on where a yield statement can appear, as described in the following.

  • Une erreur de compilation pour une instruction yield (de l’une des deux formes) s’affiche en dehors d’un method_body, operator_body ou 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
  • Il s’agit d’une erreur de compilation pour yield qu’une instruction (de l’une des deux formes) apparaisse dans une fonction anonyme.It is a compile-time error for a yield statement (of either form) to appear inside an anonymous function.
  • Il s’agit d’une erreur de compilation pour yield qu’une instruction (de l’une des deux formes finally ) apparaisse try dans la clause d’une instruction.It is a compile-time error for a yield statement (of either form) to appear in the finally clause of a try statement.
  • Il s’agit d’une erreur de compilation pour yield return qu’une instruction apparaisse n' try importe où dans une catch instruction qui contient des clauses.It is a compile-time error for a yield return statement to appear anywhere in a try statement that contains any catch clauses.

L’exemple suivant montre des utilisations valides et non yield valides d’instructions.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
}

Une conversion implicite (conversions implicites) doit exister à partir du type de l' yield return expression dans l’instruction vers le type Yield (type yield) de l’itérateur.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.

Une yield return instruction est exécutée comme suit :A yield return statement is executed as follows:

  • L’expression donnée dans l’instruction est évaluée, implicitement convertie en type yield et assignée à la Current propriété de l’objet énumérateur.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’exécution du bloc itérateur est suspendue.Execution of the iterator block is suspended. Si l' yield return instruction se trouve dans un ou try plusieurs blocs, les finally blocs associés ne sont pas exécutés pour l’instant.If the yield return statement is within one or more try blocks, the associated finally blocks are not executed at this time.
  • La MoveNext méthode de l’objet énumérateur retourne true à son appelant, ce qui indique que l’objet énumérateur a réussi à avancer jusqu’à l’élément suivant.The MoveNext method of the enumerator object returns true to its caller, indicating that the enumerator object successfully advanced to the next item.

Le prochain appel à la méthode de MoveNext l’objet énumérateur reprend l’exécution du bloc itérateur à partir de l’emplacement où il a été suspendu pour la dernière fois.The next call to the enumerator object's MoveNext method resumes execution of the iterator block from where it was last suspended.

Une yield break instruction est exécutée comme suit :A yield break statement is executed as follows:

  • Si l' yield break instruction est entourée d’un try ou de plusieurs finally blocs avec des finally blocs associés, le contrôle est initialement transféré au try bloc de l’instruction la plus profonde.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. Quand et si le contrôle atteint le point de terminaison finally d’un bloc, le contrôle est finally transféré au bloc de l’instruction try englobante suivante.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. Ce processus est répété jusqu’à finally ce que les blocs de try toutes les instructions englobantes aient été exécutés.This process is repeated until the finally blocks of all enclosing try statements have been executed.
  • Le contrôle est retourné à l’appelant du bloc Iterator.Control is returned to the caller of the iterator block. Il s’agit de MoveNext la méthode Dispose ou de la méthode de l’objet énumérateur.This is either the MoveNext method or Dispose method of the enumerator object.

Étant donné yield break qu’une instruction transfère sans condition le contrôle ailleurs, le point de yield break terminaison d’une instruction n’est jamais accessible.Because a yield break statement unconditionally transfers control elsewhere, the end point of a yield break statement is never reachable.