AnweisungenStatements

C#stellt eine Reihe von-Anweisungen bereit.C# provides a variety of statements. Die meisten dieser Anweisungen werden Entwicklern vertraut sein, die in C und C++programmiert haben.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
    ;

Das embedded_statement nicht Terminal wird für Anweisungen verwendet, die in anderen Anweisungen angezeigt werden.The embedded_statement nonterminal is used for statements that appear within other statements. Die Verwendung von embedded_statement anstelle von- Anweisungen schließt die Verwendung von Deklarations Anweisungen und bezeichneten Anweisungen in diesen Kontexten aus.The use of embedded_statement rather than statement excludes the use of declaration statements and labeled statements in these contexts. Das BeispielThe example

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

führt zu einem Kompilierzeitfehler, da eine if-Anweisung anstelle einer- Anweisung für Ihre if-Verzweigung eine embedded_statement -Anweisung erfordert.results in a compile-time error because an if statement requires an embedded_statement rather than a statement for its if branch. Wenn dieser Code zulässig ist, wird die Variable i deklariert, Sie konnte aber nie verwendet werden.If this code were permitted, then the variable i would be declared, but it could never be used. Beachten Sie jedoch, dass das Beispiel idurch Platzieren der Deklaration in einem-Block gültig ist.Note, however, that by placing i's declaration in a block, the example is valid.

Endpunkte und ErreichbarkeitEnd points and reachability

Jede-Anweisung verfügt über einen Endpunkt.Every statement has an end point. Der Endpunkt einer-Anweisung ist in intuitiver Hinsicht der Speicherort, der direkt auf die-Anweisung folgt.In intuitive terms, the end point of a statement is the location that immediately follows the statement. Die Ausführungs Regeln für zusammengesetzte Anweisungen (Anweisungen, die eingebettete Anweisungen enthalten) geben die Aktion an, die durchgeführt wird, wenn das Steuerelement den Endpunkt einer eingebetteten Anweisung erreicht.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. Wenn das Steuerelement z. b. den Endpunkt einer-Anweisung in einem-Block erreicht, wird die Steuerung an die nächste Anweisung im-Block übertragen.For example, when control reaches the end point of a statement in a block, control is transferred to the next statement in the block.

Wenn eine-Anweisung möglicherweise durch die Ausführung erreicht werden kann, wird die-Anweisung als erreichbarbezeichnet.If a statement can possibly be reached by execution, the statement is said to be reachable. Wenn es nicht möglich ist, dass eine-Anweisung ausgeführt wird, wird die-Anweisung als nicht erreichbarbezeichnet.Conversely, if there is no possibility that a statement will be executed, the statement is said to be unreachable.

Im BeispielIn the example

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

der zweite Aufruf von Console.WriteLine ist nicht erreichbar, da es nicht möglich ist, dass die Anweisung ausgeführt wird.the second invocation of Console.WriteLine is unreachable because there is no possibility that the statement will be executed.

Eine Warnung wird gemeldet, wenn der Compiler feststellt, dass eine-Anweisung nicht erreichbar ist.A warning is reported if the compiler determines that a statement is unreachable. Es ist kein Fehler, wenn eine-Anweisung nicht erreichbar ist.It is specifically not an error for a statement to be unreachable.

Um zu ermitteln, ob eine bestimmte Anweisung oder ein Endpunkt erreichbar ist, führt der Compiler die Fluss Analyse gemäß den für jede Anweisung definierten Erreichbarkeits Regeln aus.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. Die Fluss Analyse berücksichtigt die Werte konstanter Ausdrücke (Konstantenausdrücke), die das Verhalten von-Anweisungen steuern, aber die möglichen Werte von nicht konstanten Ausdrücken werden nicht berücksichtigt.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. Dies bedeutet, dass ein nicht konstanter Ausdruck eines bestimmten Typs für die Ablauf Steuerungs Analyse einen möglichen Wert dieses Typs hat.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.

Im BeispielIn the example

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

der boolesche Ausdruck der if -Anweisung ist ein konstanter Ausdruck, da beide Operanden == des Operators Konstanten sind.the boolean expression of the if statement is a constant expression because both operands of the == operator are constants. Da der Konstante Ausdruck zum Zeitpunkt der Kompilierung ausgewertet wird und den Wert falseerzeugt, Console.WriteLine wird der Aufruf als nicht erreichbar betrachtet.As the constant expression is evaluated at compile-time, producing the value false, the Console.WriteLine invocation is considered unreachable. Wenn i jedoch in eine lokale Variable geändert wirdHowever, if i is changed to be a local variable

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

der Console.WriteLine Aufruf wird als erreichbar betrachtet, obwohl er in Wirklichkeit nie ausgeführt wird.the Console.WriteLine invocation is considered reachable, even though, in reality, it will never be executed.

Der Block eines Funktionsmembers gilt immer als erreichbar.The block of a function member is always considered reachable. Wenn Sie die Erreichbarkeits Regeln der einzelnen Anweisungen in einem Block nacheinander auswerten, kann die Erreichbarkeit einer beliebigen Anweisung bestimmt werden.By successively evaluating the reachability rules of each statement in a block, the reachability of any given statement can be determined.

Im BeispielIn the example

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

die Erreichbarkeit der zweiten Console.WriteLine wird wie folgt bestimmt:the reachability of the second Console.WriteLine is determined as follows:

  • Die erste Console.WriteLine Ausdrucks Anweisung ist erreichbar, da der-Block F der-Methode erreichbar ist.The first Console.WriteLine expression statement is reachable because the block of the F method is reachable.
  • Der Endpunkt der ersten Console.WriteLine Ausdrucks Anweisung ist erreichbar, da diese Anweisung erreichbar ist.The end point of the first Console.WriteLine expression statement is reachable because that statement is reachable.
  • Die if -Anweisung ist erreichbar, da der Endpunkt der ersten Console.WriteLine Ausdrucks Anweisung erreichbar ist.The if statement is reachable because the end point of the first Console.WriteLine expression statement is reachable.
  • Die zweite Console.WriteLine Ausdrucks Anweisung ist erreichbar, da der boolesche Ausdruck if der Anweisung nicht über den konstanten Wert falseverfügt.The second Console.WriteLine expression statement is reachable because the boolean expression of the if statement does not have the constant value false.

Es gibt zwei Situationen, in denen es sich um einen Kompilierzeitfehler für den Endpunkt einer-Anweisung handelt, der erreichbar ist:There are two situations in which it is a compile-time error for the end point of a statement to be reachable:

  • Da die switch Anweisung nicht zulässt, dass ein Switch-Abschnitt zum nächsten switch-Abschnitt "durchläuft", ist dies ein Kompilierzeitfehler für den Endpunkt der Anweisungs Liste eines Switch-Abschnitts, der erreichbar ist.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. Wenn dieser Fehler auftritt, ist dies in der Regel ein Hinweis break darauf, dass eine-Anweisung fehlt.If this error occurs, it is typically an indication that a break statement is missing.
  • Es handelt sich um einen Kompilierzeitfehler für den Endpunkt des Blocks eines Funktionsmembers, der einen Wert berechnet, der erreichbar ist.It is a compile-time error for the end point of the block of a function member that computes a value to be reachable. Wenn dieser Fehler auftritt, ist dies in der Regel ein Hinweis return darauf, dass eine-Anweisung fehlt.If this error occurs, it typically is an indication that a return statement is missing.

BlöckeBlocks

Ein Block ermöglicht, mehrere Anweisungen in Kontexten zu schreiben, in denen eine einzelne Anweisung zulässig ist.A block permits multiple statements to be written in contexts where a single statement is allowed.

block
    : '{' statement_list? '}'
    ;

Ein- Block besteht aus einer optionalen statement_list (Anweisungs Liste), die in geschweiften Klammern eingeschlossen ist.A block consists of an optional statement_list (Statement lists), enclosed in braces. Wenn die Anweisungs Liste weggelassen wird, wird der Block als leer bezeichnet.If the statement list is omitted, the block is said to be empty.

Ein-Block kann Deklarations Anweisungen (Deklarations Anweisungen) enthalten.A block may contain declaration statements (Declaration statements). Der Gültigkeitsbereich einer lokalen Variablen oder Konstanten, die in einem-Block deklariert ist, ist der-Block.The scope of a local variable or constant declared in a block is the block.

Ein-Block wird wie folgt ausgeführt:A block is executed as follows:

  • Wenn der-Block leer ist, wird die Steuerung an den Endpunkt des-Blocks übertragen.If the block is empty, control is transferred to the end point of the block.
  • Wenn der Block nicht leer ist, wird die Steuerung an die Anweisungs Liste übertragen.If the block is not empty, control is transferred to the statement list. Wenn und wenn das Steuerelement den Endpunkt der Anweisungs Liste erreicht, wird die Steuerung an den Endpunkt des Blocks übertragen.When and if control reaches the end point of the statement list, control is transferred to the end point of the block.

Die Anweisungs Liste eines-Blocks ist erreichbar, wenn der Block selbst erreichbar ist.The statement list of a block is reachable if the block itself is reachable.

Der Endpunkt eines-Blocks ist erreichbar, wenn der-Block leer ist oder der Endpunkt der Anweisungs Liste erreichbar ist.The end point of a block is reachable if the block is empty or if the end point of the statement list is reachable.

Ein- Block , der eine oder yield mehrere-Anweisungen (die yield-Anweisung) enthält, wird als Iteratorblock bezeichnet.A block that contains one or more yield statements (The yield statement) is called an iterator block. Iteratorblöcke werden verwendet, um Funktionsmember als Iteratoren (Iteratoren) zu implementieren.Iterator blocks are used to implement function members as iterators (Iterators). Für iteratorblöcke gelten einige zusätzliche Einschränkungen:Some additional restrictions apply to iterator blocks:

  • Es ist ein Kompilierzeitfehler, wenn return eine Anweisung in einem Iteratorblock angezeigt wird ( yield return Anweisungen sind jedoch zulässig).It is a compile-time error for a return statement to appear in an iterator block (but yield return statements are permitted).
  • Es ist ein Kompilierzeitfehler für einen Iteratorblock, der einen unsicheren Kontext (unsichere Kontexte) enthalten soll.It is a compile-time error for an iterator block to contain an unsafe context (Unsafe contexts). Ein Iteratorblock definiert immer einen sicheren Kontext, auch wenn seine Deklaration in einem unsicheren Kontext eingebettet ist.An iterator block always defines a safe context, even when its declaration is nested in an unsafe context.

Anweisungs ListenStatement lists

Eine Anweisungs Liste besteht aus einer oder mehreren Anweisungen, die nacheinander geschrieben werden.A statement list consists of one or more statements written in sequence. Anweisungs Listen treten in Blocks (Blocks) und in switch_blocks (der Switch-Anweisung) auf.Statement lists occur in blocks (Blocks) and in switch_blocks (The switch statement).

statement_list
    : statement+
    ;

Eine Anweisungs Liste wird ausgeführt, indem die Steuerung an die erste Anweisung übertragen wird.A statement list is executed by transferring control to the first statement. Wenn und wenn das Steuerelement den Endpunkt einer-Anweisung erreicht, wird die Steuerung an die nächste Anweisung übertragen.When and if control reaches the end point of a statement, control is transferred to the next statement. Wenn und wenn das Steuerelement den Endpunkt der letzten Anweisung erreicht, wird die Steuerung an den Endpunkt der Anweisungs Liste übertragen.When and if control reaches the end point of the last statement, control is transferred to the end point of the statement list.

Eine-Anweisung in einer Anweisungs Liste ist erreichbar, wenn mindestens einer der folgenden Punkte zutrifft:A statement in a statement list is reachable if at least one of the following is true:

  • Die-Anweisung ist die erste Anweisung, und die Anweisungs Liste selbst ist erreichbar.The statement is the first statement and the statement list itself is reachable.
  • Der Endpunkt der vorhergehenden Anweisung ist erreichbar.The end point of the preceding statement is reachable.
  • Die-Anweisung ist eine Anweisung mit Bezeichnung, und auf die Bezeichnung wird goto durch eine erreichbare Anweisung verwiesen.The statement is a labeled statement and the label is referenced by a reachable goto statement.

Der Endpunkt einer Anweisungs Liste ist erreichbar, wenn der Endpunkt der letzten Anweisung in der Liste erreichbar ist.The end point of a statement list is reachable if the end point of the last statement in the list is reachable.

Die leere AnweisungThe empty statement

Ein empty_statement tut nichts.An empty_statement does nothing.

empty_statement
    : ';'
    ;

Eine leere-Anweisung wird verwendet, wenn keine Vorgänge in einem Kontext durchgeführt werden müssen, in dem eine-Anweisung erforderlich ist.An empty statement is used when there are no operations to perform in a context where a statement is required.

Durch die Ausführung einer leeren-Anweisung wird die Steuerung einfach an den Endpunkt der Anweisung übertragen.Execution of an empty statement simply transfers control to the end point of the statement. Daher ist der Endpunkt einer leeren Anweisung erreichbar, wenn die leere Anweisung erreichbar ist.Thus, the end point of an empty statement is reachable if the empty statement is reachable.

Eine leere Anweisung kann beim Schreiben einer while Anweisung mit einem NULL-Text verwendet werden:An empty statement can be used when writing a while statement with a null body:

bool ProcessMessage() {...}

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

Außerdem kann eine leere Anweisung verwendet werden, um eine Bezeichnung direkt vor dem schließenden "}" eines Blocks zu deklarieren: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: ;
}

Anweisungen mit BezeichnungLabeled statements

Ein labeled_statement ermöglicht einer-Anweisung, eine Bezeichnung als Präfix festzustellen.A labeled_statement permits a statement to be prefixed by a label. Anweisung mit Bezeichnung ist in-Blöcken zulässig, aber nicht als eingebettete Anweisungen zulässig.Labeled statements are permitted in blocks, but are not permitted as embedded statements.

labeled_statement
    : identifier ':' statement
    ;

Eine Anweisung mit Bezeichnung deklariert eine Bezeichnung mit dem Namen, der vom Bezeichnerangegeben wird.A labeled statement declares a label with the name given by the identifier. Der Gültigkeitsbereich einer Bezeichnung ist der gesamte Block, in dem die Bezeichnung deklariert wird, einschließlich aller Blöcke, die in der Liste enthalten sind.The scope of a label is the whole block in which the label is declared, including any nested blocks. Es handelt sich um einen Kompilierzeitfehler für zwei Bezeichnungen mit dem gleichen Namen, die sich überlappende Bereiche befinden.It is a compile-time error for two labels with the same name to have overlapping scopes.

Auf eine Bezeichnung kann in- goto Anweisungen (der GOTO-Anweisung) innerhalb des Bereichs der Bezeichnung verwiesen werden.A label can be referenced from goto statements (The goto statement) within the scope of the label. Dies bedeutet, goto dass-Anweisungen die Steuerung innerhalb von Blöcken und aus Blöcken, aber nie in Blöcke übertragen können.This means that goto statements can transfer control within blocks and out of blocks, but never into blocks.

Bezeichnungen verfügen über einen eigenen Deklarations Bereich und stören andere Bezeichner nicht.Labels have their own declaration space and do not interfere with other identifiers. Das BeispielThe example

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

ist gültig und verwendet den Namen x sowohl als Parameter als auch als Bezeichnung.is valid and uses the name x as both a parameter and a label.

Die Ausführung einer Anweisung mit Bezeichnung entspricht genau der Ausführung der Anweisung nach der Bezeichnung.Execution of a labeled statement corresponds exactly to execution of the statement following the label.

Zusätzlich zur Erreichbarkeit der normalen Ablauf Steuerung ist eine Anweisung mit der Bezeichnung erreichbar, wenn von einer erreichbaren goto Anweisung auf die Bezeichnung verwiesen wird.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. Distanzieren Wenn sich goto eine-Anweisung innerhalb try eines-Blocks finally befindet try, der einen-Block enthält, und die Anweisung mit der Bezeichnung außerhalb von finally liegt und der Endpunkt des Blocks nicht erreichbar ist, ist die Anweisung mit der Bezeichnung nicht erreichbar. Diese goto Anweisung.)(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.)

DeklarationsanweisungenDeclaration statements

Ein declaration_statement deklariert eine lokale Variable oder Konstante.A declaration_statement declares a local variable or constant. Deklarations Anweisungen sind in-Blöcken zulässig, aber nicht als eingebettete Anweisungen zulässig.Declaration statements are permitted in blocks, but are not permitted as embedded statements.

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

Deklarationen von lokalen VariablenLocal variable declarations

Ein local_variable_declaration deklariert eine oder mehrere lokale Variablen.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
    ;

Der local_variable_type eines local_variable_declaration gibt entweder direkt den Typ der Variablen an, die von der Deklaration eingeführt wurden, oder gibt mit dem Bezeichner an, var, dass der Typ basierend auf einem Initialisierer abgeleitet werden soll.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. Auf den Typ folgt eine Liste von local_variable_declarators, von denen jeder eine neue Variable einführt.The type is followed by a list of local_variable_declarators, each of which introduces a new variable. Ein local_variable_declarator besteht aus einem Bezeichner , der die Variable benennt, optional gefolgt von einem "="-Token und einem local_variable_initializer , das den Anfangswert der Variablen liefert.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.

Im Kontext einer lokalen Variablen Deklaration fungiert der Bezeichner var als kontextbezogenes Schlüsselwort (SchlüsselWort). Wenn local_variable_type als var angegeben wird und sich kein Typ mit dem Namen var im Gültigkeitsbereich befindet, ist die Deklaration eine implizit typisierte lokale Variablen Deklaration, deren Typ vom Typ des zugeordneten initialisiererausdrucks abgeleitet wird.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. Implizit typisierte lokale Variablen Deklarationen unterliegen den folgenden Einschränkungen:Implicitly typed local variable declarations are subject to the following restrictions:

  • Local_variable_declaration kann nicht mehrere local_variable_declarators enthalten.The local_variable_declaration cannot include multiple local_variable_declarators.
  • Local_variable_declarator muss ein local_variable_initializerenthalten.The local_variable_declarator must include a local_variable_initializer.
  • Der local_variable_initializer muss ein Ausdrucksein.The local_variable_initializer must be an expression.
  • Der initialisiererausdruck muss einen Kompilier Zeittyp aufweisen.The initializer expression must have a compile-time type.
  • Der initialisiererausdruck kann nicht auf die deklarierte Variable selbst verweisen.The initializer expression cannot refer to the declared variable itself

Im folgenden finden Sie Beispiele für falsche implizit typisierte lokale Variablen Deklarationen: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

Der Wert einer lokalen Variablen wird in einem Ausdruck mithilfe eines Simple_name (simple names) abgerufen, und der Wert einer lokalen Variablen wird mithilfe einer Zuweisung (Zuweisungs Operatoren) geändert.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). Eine lokale Variable muss an jedem Speicherort, an dem ihr Wert abgerufen wird, definitiv zugewiesen werden (definitive Zuweisung).A local variable must be definitely assigned (Definite assignment) at each location where its value is obtained.

Der Gültigkeitsbereich einer lokalen Variablen, die in einem local_variable_declaration deklariert ist, ist der Block, in dem die Deklaration auftritt.The scope of a local variable declared in a local_variable_declaration is the block in which the declaration occurs. Es ist ein Fehler, auf eine lokale Variable in einer Textposition zu verweisen, die der local_variable_declarator der lokalen Variablen vorangestellt ist.It is an error to refer to a local variable in a textual position that precedes the local_variable_declarator of the local variable. Innerhalb des Gültigkeits Bereichs einer lokalen Variablen ist es ein Kompilierzeitfehler, eine andere lokale Variable oder Konstante mit dem gleichen Namen zu deklarieren.Within the scope of a local variable, it is a compile-time error to declare another local variable or constant with the same name.

Eine lokale Variablen Deklaration, die mehrere Variablen deklariert, entspricht mehreren Deklarationen von einzelnen Variablen mit demselben Typ.A local variable declaration that declares multiple variables is equivalent to multiple declarations of single variables with the same type. Außerdem entspricht ein Variableninitialisierer in einer lokalen Variablen Deklaration genau einer Zuweisungsanweisung, die unmittelbar nach der Deklaration eingefügt wird.Furthermore, a variable initializer in a local variable declaration corresponds exactly to an assignment statement that is inserted immediately after the declaration.

Das BeispielThe example

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

entspricht genaucorresponds exactly to

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

In einer implizit typisierten lokalen Variablen Deklaration wird der Typ der zu deklarierenden lokalen Variablen mit dem Typ des Ausdrucks, der zum Initialisieren der Variablen verwendet wird, identisch sein.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. Zum Beispiel: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>();

Die oben genannten implizit typisierten lokalen Variablen Deklarationen entsprechen genau den folgenden explizit typisierten Deklarationen: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>();

Lokale Konstante DeklarationenLocal constant declarations

Ein local_constant_declaration deklariert eine oder mehrere lokale Konstanten.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
    ;

Der Typ eines local_constant_declaration gibt den Typ der Konstanten an, die von der Deklaration eingeführt wurden.The type of a local_constant_declaration specifies the type of the constants introduced by the declaration. Auf den Typ folgt eine Liste von constant_declarators, von denen jeder eine neue Konstante einführt.The type is followed by a list of constant_declarators, each of which introduces a new constant. Ein constant_declarator besteht aus einem Bezeichner , der die Konstante benennt, gefolgt von einem "="-Token, gefolgt von einem constant_expression (Konstantenausdrücken), der den Wert der Konstante liefert.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.

Der- Typ und der constant_expression -Wert einer lokalen Konstanten Deklaration müssen dieselben Regeln wie die einer Konstanten Element Deklaration (Konstanten) einhalten.The type and constant_expression of a local constant declaration must follow the same rules as those of a constant member declaration (Constants).

Der Wert einer lokalen Konstante wird in einem Ausdruck mithilfe eines Simple_name (simple names) abgerufen.The value of a local constant is obtained in an expression using a simple_name (Simple names).

Der Gültigkeitsbereich einer lokalen Konstante ist der Block, in dem die Deklaration auftritt.The scope of a local constant is the block in which the declaration occurs. Es ist ein Fehler, auf eine lokale Konstante in einer Textposition zu verweisen, die der constant_declaratorvorausgeht.It is an error to refer to a local constant in a textual position that precedes its constant_declarator. Innerhalb des Gültigkeits Bereichs einer lokalen Konstante handelt es sich um einen Kompilierzeitfehler, um eine andere lokale Variable oder Konstante mit dem gleichen Namen zu deklarieren.Within the scope of a local constant, it is a compile-time error to declare another local variable or constant with the same name.

Eine lokale Konstantendeklaration, die mehrere Konstanten deklariert, entspricht mehreren Deklarationen von einzelnen Konstanten desselben Typs.A local constant declaration that declares multiple constants is equivalent to multiple declarations of single constants with the same type.

AusdrucksanweisungenExpression statements

Ein expression_statement wertet einen angegebenen Ausdruck aus.An expression_statement evaluates a given expression. Der von dem Ausdruck berechnete Wert, falls vorhanden, wird verworfen.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
    ;

Nicht alle Ausdrücke sind als Anweisungen zulässig.Not all expressions are permitted as statements. Insbesondere Ausdrücke wie x + y und, die nur x == 1 einen Wert berechnen (der verworfen wird), sind nicht als-Anweisungen zulässig.In particular, expressions such as x + y and x == 1 that merely compute a value (which will be discarded), are not permitted as statements.

Die Ausführung eines expression_statement wertet den enthaltenen Ausdruck aus und überträgt dann die Steuerung an den Endpunkt des expression_statement.Execution of an expression_statement evaluates the contained expression and then transfers control to the end point of the expression_statement. Der Endpunkt eines expression_statement ist erreichbar, wenn dieser expression_statement erreichbar ist.The end point of an expression_statement is reachable if that expression_statement is reachable.

AuswahlanweisungenSelection statements

Auswahl Anweisungen wählen Sie eine der möglichen Anweisungen für die Ausführung basierend auf dem Wert eines Ausdrucks aus.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
    ;

Die if-AnweisungThe if statement

Die if -Anweisung wählt eine Anweisung für die Ausführung basierend auf dem Wert eines booleschen Ausdrucks aus.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
    ;

Ein else Teil ist mit dem lexikalisch nächstgelegenen if vorangehenden-Element verknüpft, das von der Syntax zugelassen wird.An else part is associated with the lexically nearest preceding if that is allowed by the syntax. Folglich eine if -Anweisung der FormThus, an if statement of the form

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

für die folgende Syntax:is equivalent to

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

Eine if -Anweisung wird wie folgt ausgeführt:An if statement is executed as follows:

  • Die Boolean_expression (boolesche Ausdrücke) werden ausgewertet.The boolean_expression (Boolean expressions) is evaluated.
  • Wenn der boolesche Ausdruck ergibt true, wird die Steuerung an die erste eingebettete Anweisung übertragen.If the boolean expression yields true, control is transferred to the first embedded statement. Wenn und wenn das Steuerelement den Endpunkt dieser Anweisung erreicht, wird die Steuerung an den Endpunkt if der Anweisung übertragen.When and if control reaches the end point of that statement, control is transferred to the end point of the if statement.
  • Wenn der boolesche Ausdruck ergibt false und ein else Teil vorhanden ist, wird die Steuerung an die zweite eingebettete Anweisung übertragen.If the boolean expression yields false and if an else part is present, control is transferred to the second embedded statement. Wenn und wenn das Steuerelement den Endpunkt dieser Anweisung erreicht, wird die Steuerung an den Endpunkt if der Anweisung übertragen.When and if control reaches the end point of that statement, control is transferred to the end point of the if statement.
  • Wenn der boolesche Ausdruck ergibt false und ein else Teil nicht vorhanden ist, wird die Steuerung an if den Endpunkt der Anweisung übertragen.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.

Die erste eingebettete Anweisung einer if -Anweisung ist erreichbar, if wenn die-Anweisung erreichbar ist und der boolesche Ausdruck nicht über den falseKonstanten Wert verfügt.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.

Die zweite eingebettete Anweisung einer if -Anweisung (falls vorhanden) ist erreichbar, if wenn die-Anweisung erreichbar ist und der boolesche Ausdruck nicht über den trueKonstanten Wert verfügt.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.

Der Endpunkt if einer-Anweisung ist erreichbar, wenn der Endpunkt von mindestens einer der eingebetteten Anweisungen erreichbar ist.The end point of an if statement is reachable if the end point of at least one of its embedded statements is reachable. Außerdem ist der if Endpunkt einer-Anweisung ohne else Teil erreichbar, wenn die if -Anweisung erreichbar ist und der boolesche Ausdruck nicht über den konstanten Wert trueverfügt.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.

Die Switch-AnweisungThe switch statement

Die Switch-Anweisung wählt für die Ausführung eine Anweisungs Liste mit einer zugeordneten Switch-Bezeichnung aus, die dem Wert des switch-Ausdrucks entspricht.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' ':'
    ;

Ein switch_statement besteht aus dem Schlüsselwort switch, gefolgt von einem Ausdruck in Klammern (der als Switch-Ausdruck bezeichnet wird), gefolgt von einem switch_block.A switch_statement consists of the keyword switch, followed by a parenthesized expression (called the switch expression), followed by a switch_block. Der switch_block besteht aus null oder mehr switch_sections, der in geschweiften Klammern eingeschlossen ist.The switch_block consists of zero or more switch_sections, enclosed in braces. Jede switch_section besteht aus mindestens einer switch_labels, gefolgt von einer statement_list (Anweisungs Liste).Each switch_section consists of one or more switch_labels followed by a statement_list (Statement lists).

Der governancetyp einer switch Anweisung wird durch den Switch-Ausdruck festgelegt.The governing type of a switch statement is established by the switch expression.

  • Wenn der Switch-Ausdruck sbyte, byte, short, ushort, int, uint, long, ulong, bool, char, 0 oder ein enum_type, oder wenn es sich um den Typ handelt, der NULL-Werte zulässt, der einem dieser Typen entspricht. , dann ist dies der regierende Typ der 2-Anweisung.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.
  • Andernfalls muss genau eine benutzerdefinierte implizite Konvertierung (benutzerdefinierte Konvertierungen) sbytevom Typ des switch-Ausdrucks bis zu einem der folgenden möglichen governancetypen vorhanden sein:, byte,, ushort short , int, uint, ,long ,char,oder, ein Typ, der NULL-Werte zulässt, der einem dieser Typen entspricht. 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.
  • Andernfalls tritt ein Kompilierzeitfehler auf, wenn keine solche implizite Konvertierung vorhanden ist oder wenn mehr als eine implizite Konvertierung vorhanden ist.Otherwise, if no such implicit conversion exists, or if more than one such implicit conversion exists, a compile-time error occurs.

Der Konstante Ausdruck jeder case Bezeichnung muss einen Wert angeben, der implizit konvertierbar (implizite Konvertierungen) in den richtentyp switch der Anweisung ist.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. Ein Kompilierzeitfehler tritt auf, wenn zwei case oder mehr Bezeichnungen in switch derselben Anweisung denselben Konstanten Wert angeben.A compile-time error occurs if two or more case labels in the same switch statement specify the same constant value.

In einer Switch-Anweisung darf default höchstens eine Bezeichnung vorhanden sein.There can be at most one default label in a switch statement.

Eine switch -Anweisung wird wie folgt ausgeführt:A switch statement is executed as follows:

  • Der Switch-Ausdruck wird ausgewertet und in den regierenden Typ konvertiert.The switch expression is evaluated and converted to the governing type.
  • Wenn eine der Konstanten, die in einer case Bezeichnung in derselben switch Anweisung angegeben ist, gleich dem Wert des switch-Ausdrucks ist, wird die Steuerung an die Anweisungs Liste nach case der passenden Bezeichnung übertragen.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.
  • Wenn keine der Konstanten, die in case Bezeichnungen in derselben switch Anweisung angegeben sind, gleich dem Wert des switch-Ausdrucks ist und eine default Bezeichnung vorhanden ist, wird die Steuerung an die Anweisungs Liste übertragen default , die nach dem ETI.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.
  • Wenn keine der Konstanten, die in case Bezeichnungen in derselben switch Anweisung angegeben sind, gleich dem Wert des switch-Ausdrucks ist, und wenn default keine Bezeichnung vorhanden ist, switch wird die Steuerung an den Endpunkt der Anweisung übertragen.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.

Wenn der Endpunkt der Anweisungs Liste eines Switch-Abschnitts erreichbar ist, tritt ein Kompilierzeitfehler auf.If the end point of the statement list of a switch section is reachable, a compile-time error occurs. Dies wird als "No FallThrough"-Regel bezeichnet.This is known as the "no fall through" rule. Das BeispielThe example

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

ist gültig, da kein Switch-Abschnitt über einen erreichbaren Endpunkt verfügt.is valid because no switch section has a reachable end point. Anders als bei C++C und ist die Ausführung eines Switch-Abschnitts nicht zulässig, um zum nächsten switchabschnitt zu wechseln, und das BeispielUnlike 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();
}

führt zu einem Kompilierzeitfehler.results in a compile-time error. Wenn die Ausführung eines Switch-Abschnitts durch die Ausführung eines anderen Switch-Abschnitts befolgt werden soll, goto case muss goto default eine explizite-oder-Anweisung verwendet werden: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;
}

Mehrere Bezeichnungen sind in einem switch_sectionzulässig.Multiple labels are permitted in a switch_section. Das BeispielThe example

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

ist gültig.is valid. Das Beispiel verstößt nicht gegen die Regel "No FallThrough", da die Bezeichnungen case 2: und default: Teil desselben switch_sectionsind.The example does not violate the "no fall through" rule because the labels case 2: and default: are part of the same switch_section.

Die "No FallThrough"-Regel verhindert eine gängige Klasse von Fehlern, die in C C++ auftreten break , und wenn Anweisungen versehentlich ausgelassen werden.The "no fall through" rule prevents a common class of bugs that occur in C and C++ when break statements are accidentally omitted. Außerdem können die Switch-Abschnitte einer switch Anweisung aufgrund dieser Regel beliebig neu angeordnet werden, ohne dass sich dies auf das Verhalten der Anweisung auswirkt.In addition, because of this rule, the switch sections of a switch statement can be arbitrarily rearranged without affecting the behavior of the statement. Beispielsweise können die Abschnitte der switch obigen Anweisung umgekehrt werden, ohne dass sich dies auf das Verhalten der-Anweisung auswirkt: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;
}

Die Anweisungs Liste eines Switch-Abschnitts endet in der breakRegel goto casemit einer goto default -,-oder-Anweisung, aber alle Konstrukte, die den Endpunkt der Anweisungs Liste nicht erreichbar rendern, sind zulässig.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. Beispielsweise ist es while bekannt, dass eine vom booleschen true Ausdruck gesteuerte Anweisung den Endpunkt niemals erreicht.For example, a while statement controlled by the boolean expression true is known to never reach its end point. Ebenso überträgt eine throw - return oder-Anweisung immer an eine andere Stelle und erreicht ihren Endpunkt nicht.Likewise, a throw or return statement always transfers control elsewhere and never reaches its end point. Daher ist das folgende Beispiel gültig:Thus, the following example is valid:

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

Der governancetyp einer switch Anweisung kann der Typ stringsein.The governing type of a switch statement may be the type string. Zum Beispiel: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;
    }
}

Wie bei Zeichen folgen Gleichheits Operatoren (Zeichen folgen Gleichheits Operatoren) wird bei der Anweisung die switch Groß-/Kleinschreibung beachtet, und es wird nur ein bestimmter Schalter Abschnitt ausgeführt, wenn die case Zeichenfolge des switch-AusdrucksLike 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.

Wenn der governancetyp einer switch -Anweisung stringist, ist null der Wert als Konstante für die Case-Bezeichnung zulässig.When the governing type of a switch statement is string, the value null is permitted as a case label constant.

Die statement_lists eines switch_block können Deklarations Anweisungen (Deklarations Anweisungen) enthalten.The statement_lists of a switch_block may contain declaration statements (Declaration statements). Der Gültigkeitsbereich einer lokalen Variablen oder Konstanten, die in einem Switch-Block deklariert ist, ist der Switch-Block.The scope of a local variable or constant declared in a switch block is the switch block.

Die Anweisungs Liste eines bestimmten switchabschnitts ist erreichbar, wenn switch die-Anweisung erreichbar ist und mindestens einer der folgenden Punkte zutrifft: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:

  • Der Switch-Ausdruck ist ein nicht konstanter Wert.The switch expression is a non-constant value.
  • Der Switch-Ausdruck ist ein konstanter Wert, der case mit einer Bezeichnung im Switch-Abschnitt übereinstimmt.The switch expression is a constant value that matches a case label in the switch section.
  • Der Switch-Ausdruck ist ein konstanter Wert, der keiner case Bezeichnung entspricht, und der Switch-Abschnitt default enthält die Bezeichnung.The switch expression is a constant value that doesn't match any case label, and the switch section contains the default label.
  • Auf eine Switch-Bezeichnung des Switch-Abschnitts wird durch eine goto case erreichbare-oder goto default -Anweisung verwiesen.A switch label of the switch section is referenced by a reachable goto case or goto default statement.

Der Endpunkt einer switch -Anweisung ist erreichbar, wenn mindestens einer der folgenden Punkte zutrifft:The end point of a switch statement is reachable if at least one of the following is true:

  • Die switch -Anweisung enthält eine break erreichbare Anweisung, switch die die-Anweisung beendet.The switch statement contains a reachable break statement that exits the switch statement.
  • Die switch -Anweisung ist erreichbar, der Switch-Ausdruck ist ein nicht konstanter Wert, und default es ist keine Bezeichnung vorhanden.The switch statement is reachable, the switch expression is a non-constant value, and no default label is present.
  • Die switch -Anweisung ist erreichbar, der Switch-Ausdruck ist ein konstanter Wert, der case keiner Bezeichnung entspricht, default und es ist keine Bezeichnung vorhanden.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.

IterationsanweisungenIteration statements

Iterations Anweisungen führen eine eingebettete Anweisung wiederholt aus.Iteration statements repeatedly execute an embedded statement.

iteration_statement
    : while_statement
    | do_statement
    | for_statement
    | foreach_statement
    ;

Die while-AnweisungThe while statement

Die while -Anweisung führt eine eingebettete Anweisung bedingt NULL oder mehrmals aus.The while statement conditionally executes an embedded statement zero or more times.

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

Eine while -Anweisung wird wie folgt ausgeführt:A while statement is executed as follows:

  • Die Boolean_expression (boolesche Ausdrücke) werden ausgewertet.The boolean_expression (Boolean expressions) is evaluated.
  • Wenn der boolesche Ausdruck ergibt true, wird die Steuerung an die eingebettete Anweisung übertragen.If the boolean expression yields true, control is transferred to the embedded statement. Wenn und wenn das Steuerelement den Endpunkt der eingebetteten Anweisung erreicht (möglicherweise aus der Ausführung continue einer-Anweisung), wird die Steuerung an den Anfang while der Anweisung übertragen.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.
  • Wenn der boolesche Ausdruck ergibt false, wird die Steuerung an den Endpunkt while der Anweisung übertragen.If the boolean expression yields false, control is transferred to the end point of the while statement.

Innerhalb der eingebetteten Anweisung while einer-Anweisung kann eine break -Anweisung (die Break-Anweisung) verwendet werden, um die while Steuerung an den Endpunkt der-Anweisung zu übertragen (wodurch die Iterationen der eingebetteten- Anweisungbeendetwerden).continue die-Anweisung (die Continue-Anweisung) kann verwendet werden, um die Steuerung an den Endpunkt der eingebetteten Anweisung zu übertragen (wodurch eine while andere Iterations Anweisung ausgeführt wird).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).

Die eingebettete Anweisung einer while -Anweisung ist erreichbar, while wenn die-Anweisung erreichbar ist und der boolesche Ausdruck nicht über den falseKonstanten Wert verfügt.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.

Der Endpunkt einer while -Anweisung ist erreichbar, wenn mindestens einer der folgenden Punkte zutrifft:The end point of a while statement is reachable if at least one of the following is true:

  • Die while -Anweisung enthält eine break erreichbare Anweisung, while die die-Anweisung beendet.The while statement contains a reachable break statement that exits the while statement.
  • Die while -Anweisung ist erreichbar, und der boolesche Ausdruck weist nicht den Konstanten trueWert auf.The while statement is reachable and the boolean expression does not have the constant value true.

Die Do-AnweisungThe do statement

Die do Anweisung führt mindestens einmal eine eingebettete Anweisung aus.The do statement conditionally executes an embedded statement one or more times.

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

Eine do -Anweisung wird wie folgt ausgeführt:A do statement is executed as follows:

  • Das Steuerelement wird an die eingebettete Anweisung übertragen.Control is transferred to the embedded statement.
  • Wenn und wenn das Steuerelement den Endpunkt der eingebetteten Anweisung erreicht (möglicherweise aus der Ausführung einer continue-Anweisung), wird die Boolean_expression (boolesche Ausdrücke) ausgewertet.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. Wenn der boolesche Ausdruck ergibt true, wird die Steuerung an den Anfang do der Anweisung übertragen.If the boolean expression yields true, control is transferred to the beginning of the do statement. Andernfalls wird die Steuerung an den Endpunkt do der Anweisung übertragen.Otherwise, control is transferred to the end point of the do statement.

Innerhalb der eingebetteten Anweisung do einer-Anweisung kann eine break -Anweisung (die Break-Anweisung) verwendet werden, um die do Steuerung an den Endpunkt der-Anweisung zu übertragen (wodurch die Iterationen der eingebetteten- Anweisungbeendetwerden).continue die-Anweisung (die Continue-Anweisung) kann verwendet werden, um die Steuerung an den Endpunkt der eingebetteten Anweisung zu übertragen.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.

Die eingebettete Anweisung einer do -Anweisung ist erreichbar, do wenn die-Anweisung erreichbar ist.The embedded statement of a do statement is reachable if the do statement is reachable.

Der Endpunkt einer do -Anweisung ist erreichbar, wenn mindestens einer der folgenden Punkte zutrifft:The end point of a do statement is reachable if at least one of the following is true:

  • Die do -Anweisung enthält eine break erreichbare Anweisung, do die die-Anweisung beendet.The do statement contains a reachable break statement that exits the do statement.
  • Der Endpunkt der eingebetteten Anweisung ist erreichbar, und der boolesche Ausdruck weist nicht den konstanten Wert trueauf.The end point of the embedded statement is reachable and the boolean expression does not have the constant value true.

Die for-AnweisungThe for statement

Die for -Anweisung wertet eine Sequenz von Initialisierungs Ausdrücken aus und führt dann, während eine Bedingung true ist, wiederholt eine eingebettete Anweisung aus und wertet eine Sequenz von Iterations Ausdrücken aus.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)*
    ;

For_initializer, falls vorhanden, besteht entweder aus einer local_variable_declaration (lokale Variablen Deklarationen) oder einer Liste von statement_expressions (Ausdrucks Anweisungen), die durch Kommas getrennt sind.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. Der Gültigkeitsbereich einer lokalen Variablen, die von einem for_initializer deklariert wird, beginnt bei local_variable_declarator für die Variable und reicht bis zum Ende der eingebetteten Anweisung aus.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. Der Bereich umfasst for_condition und for_iterator.The scope includes the for_condition and the for_iterator.

Der for_conditionmuss, falls vorhanden, ein Boolean_expression (boolescher Ausdruck) sein.The for_condition, if present, must be a boolean_expression (Boolean expressions).

Der for_iteratorbesteht, falls vorhanden, aus einer Liste von statement_expressions (Ausdrucks Anweisungen), die durch Kommas getrennt sind.The for_iterator, if present, consists of a list of statement_expressions (Expression statements) separated by commas.

Eine for-Anweisung wird wie folgt ausgeführt:A for statement is executed as follows:

  • Wenn ein for_initializer vorhanden ist, werden die Variableninitialisierer oder Anweisungs Ausdrücke in der Reihenfolge ausgeführt, in der Sie geschrieben werden.If a for_initializer is present, the variable initializers or statement expressions are executed in the order they are written. Dieser Schritt wird nur einmal ausgeführt.This step is only performed once.
  • Wenn ein for_condition vorhanden ist, wird es ausgewertet.If a for_condition is present, it is evaluated.
  • Wenn for_condition nicht vorhanden ist oder die Auswertung true ergibt, wird die Steuerung an die eingebettete Anweisung übertragen.If the for_condition is not present or if the evaluation yields true, control is transferred to the embedded statement. Wenn und wenn das Steuerelement den Endpunkt der eingebetteten Anweisung erreicht (möglicherweise aus der Ausführung einer continue-Anweisung), werden die Ausdrücke des for_iterator, sofern vorhanden, nacheinander ausgewertet. Anschließend wird eine weitere Iterationen ausgeführt, beginnend mit Auswertung des for_condition im obigen Schritt.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.
  • Wenn for_condition vorhanden ist und die Auswertung false ergibt, wird die Steuerung an den Endpunkt der for-Anweisung übertragen.If the for_condition is present and the evaluation yields false, control is transferred to the end point of the for statement.

Innerhalb der eingebetteten Anweisung einer for-Anweisung kann eine break-Anweisung (die Break-Anweisung) verwendet werden, um die Steuerung an den Endpunkt der for-Anweisung (d. h. die Iterations Ende der eingebetteten Anweisung) und eine continue-Anweisung ( Die Continue-Anweisung) kann verwendet werden, um die Steuerung an den Endpunkt der eingebetteten Anweisung zu übertragen (d. h., der for_iterator wird ausgeführt, und es wird eine weitere Iterations Anweisung der for-Anweisung ausgeführt, beginnend mit dem 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).

Die eingebettete Anweisung einer for -Anweisung ist erreichbar, wenn eine der folgenden Aussagen zutrifft:The embedded statement of a for statement is reachable if one of the following is true:

  • Die for-Anweisung ist erreichbar, und es ist keine for_condition vorhanden.The for statement is reachable and no for_condition is present.
  • Die for-Anweisung ist erreichbar, und ein for_condition ist vorhanden und weist nicht den konstanten Wert false auf.The for statement is reachable and a for_condition is present and does not have the constant value false.

Der Endpunkt einer for -Anweisung ist erreichbar, wenn mindestens einer der folgenden Punkte zutrifft:The end point of a for statement is reachable if at least one of the following is true:

  • Die for -Anweisung enthält eine break erreichbare Anweisung, for die die-Anweisung beendet.The for statement contains a reachable break statement that exits the for statement.
  • Die for-Anweisung ist erreichbar, und ein for_condition ist vorhanden und weist nicht den konstanten Wert true auf.The for statement is reachable and a for_condition is present and does not have the constant value true.

Die foreach-AnweisungThe foreach statement

Die foreach -Anweisung zählt die Elemente einer Auflistung auf und führt eine eingebettete Anweisung für jedes Element der Auflistung aus.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
    ;

Der Typ und der Bezeichner einer foreach -Anweisung deklarieren die iterations Variable der-Anweisung.The type and identifier of a foreach statement declare the iteration variable of the statement. Wenn der Bezeichner "var" als local_variable_typeangegeben wird und kein Typ mit dem Namen var im Gültigkeitsbereich ist, wird die Iterations Variable als implizit typisierte Iterations Variablebezeichnet, und ihr Typ wird als Elementtyp des foreach verwendet. -Anweisung, wie unten angegeben.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. Die Iterations Variable entspricht einer schreibgeschützten lokalen Variablen mit einem Bereich, der die eingebettete Anweisung erweitert.The iteration variable corresponds to a read-only local variable with a scope that extends over the embedded statement. Während der Ausführung einer foreach -Anweisung stellt die Iterations Variable das Auflistungs Element dar, für das zurzeit eine Iterations Ausführung ausgeführt wird.During execution of a foreach statement, the iteration variable represents the collection element for which an iteration is currently being performed. Ein Kompilierzeitfehler tritt auf, wenn die eingebettete Anweisung versucht, die Iterations Variable (über die ++ - -- und-Operatoren) zu ändern oder die ref Iterations out Variable als-oder-Parameter zu übergeben.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.

Im folgenden wird IEnumerableaus Gründen IEnumerator System.Collections IEnumerable<T> der Übersichtlichkeit,, IEnumerator<T> und auf die entsprechenden Typen in den-Namespaces System.Collections.Genericund verwiesen.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.

Die Kompilierzeit Verarbeitung einer foreach-Anweisung bestimmt zuerst den Auflistungstyp, den Enumeratortyp und den Elementtyp des Ausdrucks.The compile-time processing of a foreach statement first determines the collection type, enumerator type and element type of the expression. Diese Bestimmung verläuft wie folgt:This determination proceeds as follows:

  • Wenn der Typ X des Ausdrucks ein Arraytyp ist, gibt es eine implizite Verweis Konvertierung X von in IEnumerable die-Schnitt System.Array Stelle (da diese Schnittstelle implementiert).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). Der Sammlungstyp ist IEnumerable die-Schnittstelle, der Enumeratortyp ist die IEnumerator -Schnittstelle, und der Elementtyp ist der XElementtyp des Arraytyps.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.

  • Wenn der Typ X des Ausdrucks ist dynamic , gibt es eine implizite Konvertierung von einem Ausdruck in IEnumerable die-Schnittstelle (implizite dynamische Konvertierungen).If the type X of expression is dynamic then there is an implicit conversion from expression to the IEnumerable interface (Implicit dynamic conversions). Der Sammlungstyp ist IEnumerable die-Schnittstelle, und der Enumeratortyp ist die IEnumerator -Schnittstelle.The collection type is the IEnumerable interface and the enumerator type is the IEnumerator interface. Wenn der Bezeichner "var" als local_variable_type angegeben wird, ist der Elementtyp dynamic; andernfalls ist er object.If the var identifier is given as the local_variable_type then the element type is dynamic, otherwise it is object.

  • Stellen Sie andernfalls fest, ob X der Typ über GetEnumerator eine geeignete Methode verfügt:Otherwise, determine whether the type X has an appropriate GetEnumerator method:

    • Führt eine Element Suche für den Typ X mit Bezeichnern GetEnumerator und ohne Typargumente durch.Perform member lookup on the type X with identifier GetEnumerator and no type arguments. Wenn die Element Suche keine Entsprechung erzeugt oder eine Mehrdeutigkeit erzeugt oder eine Entsprechung erzeugt, die keine Methoden Gruppe ist, überprüfen Sie wie unten beschrieben, ob eine Aufzähl Bare-Schnittstelle vorliegt.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. Es wird empfohlen, dass eine Warnung ausgegeben wird, wenn die Element Suche nur eine Methoden Gruppe oder keine Entsprechung erzeugt.It is recommended that a warning be issued if member lookup produces anything except a method group or no match.
    • Führt die Überladungs Auflösung mithilfe der resultierenden Methoden Gruppe und einer leeren Argumentliste durch.Perform overload resolution using the resulting method group and an empty argument list. Wenn die Überladungs Auflösung keine anwendbaren Methoden zur Folge hat, zu einer Mehrdeutigkeit führt oder zu einer einzigen optimalen Methode führt, diese Methode jedoch entweder statisch oder nicht öffentlich ist, überprüfen Sie, wie unten beschrieben, eine Aufzähl Bare Schnittstelle.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. Es wird empfohlen, dass eine Warnung ausgegeben wird, wenn die Überladungs Auflösung nur eine eindeutige öffentliche Instanzmethode oder keine anwendbaren Methoden erzeugt.It is recommended that a warning be issued if overload resolution produces anything except an unambiguous public instance method or no applicable methods.
    • Wenn der E Rückgabetyp GetEnumerator der Methode keine Klasse, Struktur oder Schnittstellentyp ist, wird ein Fehler erzeugt, und es werden keine weiteren Schritte ausgeführt.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.
    • Die Element Suche erfolgt E mit dem-Bezeichner Current und ohne Typargumente.Member lookup is performed on E with the identifier Current and no type arguments. Wenn die Member-Suche keine Entsprechung erzeugt, ist das Ergebnis ein Fehler, oder es handelt sich um ein anderes Ergebnis als eine öffentliche Instanzeigenschaft, die Lesevorgänge zulässt, es wird ein Fehler erzeugt, und es werden keine weiteren Schritte ausgeführt.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.
    • Die Element Suche erfolgt E mit dem-Bezeichner MoveNext und ohne Typargumente.Member lookup is performed on E with the identifier MoveNext and no type arguments. Wenn die Member-Suche keine Entsprechung erzeugt, ist das Ergebnis ein Fehler, oder es handelt sich um ein anderes Ergebnis als eine Methoden Gruppe. es wird ein Fehler erzeugt, und es werden keine weiteren Schritte ausgeführt.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.
    • Die Überladungs Auflösung wird für die Methoden Gruppe mit einer leeren Argumentliste ausgeführt.Overload resolution is performed on the method group with an empty argument list. Wenn die Überladungs Auflösung keine anwendbaren Methoden zur Folge hat, führt dies zu einer Mehrdeutigkeit, oder führt dies zu einer einzigen optimalen Methode, aber diese Methode ist entweder statisch oder nicht öffentlich bool, oder der Rückgabetyp ist nicht. es wird ein Fehler erzeugt, und es werden keine weiteren Schritte ausgeführt.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.
    • Der Auflistungstyp ist X, der Enumeratortyp ist E, Current und der Elementtyp ist der Typ der Eigenschaft.The collection type is X, the enumerator type is E, and the element type is the type of the Current property.
  • Überprüfen Sie andernfalls eine Aufzähl Bare-Schnittstelle:Otherwise, check for an enumerable interface:

    • Wenn zwischen Ti allen Typen, für die eine implizite Konvertierung von X in IEnumerable<Ti>vorhanden ist, gibt es einen eindeutigen Typ T , der T nicht dynamic ist und für alle anderen Ti ein implizite Konvertierung von IEnumerable<T> in IEnumerable<Ti>, dann ist der Sammlungstyp die IEnumerable<T>-Schnittstelle, der Enumeratortyp ist die-Schnittstelle IEnumerator<T>, und der Elementtyp ist 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.
    • Andernfalls wird ein Fehler erzeugt, wenn mehr als ein Tsolcher Typ vorhanden ist, und es werden keine weiteren Schritte ausgeführt.Otherwise, if there is more than one such type T, then an error is produced and no further steps are taken.
    • Andernfalls X ist bei einer impliziten Konvertierung von in die System.Collections.IEnumerable -Schnittstelle der Sammlungstyp diese Schnittstelle, der Enumeratortyp ist die-Schnitt System.Collections.IEnumeratorStelle, und der Elementtyp ist. 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.
    • Andernfalls wird ein Fehler erzeugt, und es werden keine weiteren Schritte ausgeführt.Otherwise, an error is produced and no further steps are taken.

Die oben genannten Schritte, wenn erfolgreich, führen zu einer eindeutigen CGenerierung eines Auflistungs E Typs, enumeratortyps und Elementtyps T.The above steps, if successful, unambiguously produce a collection type C, enumerator type E and element type T. Eine foreach-Anweisung des FormularsA foreach statement of the form

foreach (V v in x) embedded_statement

wird dann auf erweitert:is then expanded to:

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

Die Variable e ist für den Ausdruck x oder die eingebettete Anweisung oder einen anderen Quellcode des Programms nicht sichtbar oder kann nicht darauf zugegriffen werden.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. Die Variable v ist in der eingebetteten Anweisung schreibgeschützt.The variable v is read-only in the embedded statement. Wenn keine explizite Konvertierung (explizite Konvertierungen) von T (dem Elementtyp) in V (der local_variable_type in der foreach-Anweisung) vorhanden ist, wird ein Fehler erzeugt, und es werden keine weiteren Schritte ausgeführt.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. Wenn x den Wert nullhat, wird System.NullReferenceException zur Laufzeit eine ausgelöst.If x has the value null, a System.NullReferenceException is thrown at run-time.

Eine Implementierung darf eine bestimmte foreach-Anweisung anders implementieren, z. b. aus Leistungsgründen, solange das Verhalten mit der obigen Erweiterung konsistent ist.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.

Die Platzierung von v innerhalb der while-Schleife ist wichtig für die Erfassung durch eine anonyme Funktion, die in embedded_statementauftritt.The placement of v inside the while loop is important for how it is captured by any anonymous function occurring in the embedded_statement.

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

Wenn v außerhalb der while-Schleife deklariert wurde, wird Sie von allen Iterationen gemeinsam genutzt, und ihr Wert nach der for-Schleife wäre der endgültige 13Wert,, der den Aufruf von f druckt.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. Da jede Iterations Variable über eine eigene Variable vverfügt, hält die, die von f in der ersten Iterationen aufgezeichnet wird, den Wert 7, der gedruckt wird, weiterhin.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. (Hinweis: frühere Versionen von C# , v die außerhalb der while-Schleife deklariert wurden.)(Note: earlier versions of C# declared v outside of the while loop.)

Der Hauptteil des Blocks zum Schluss wird gemäß den folgenden Schritten erstellt:The body of the finally block is constructed according to the following steps:

  • Wenn eine implizite Konvertierung von E in die System.IDisposable -Schnittstelle erfolgt, dannIf there is an implicit conversion from E to the System.IDisposable interface, then

    • Wenn E ein Werttyp ist, der keine NULL-Werte zulässt, wird die schließlich-Klausel auf die semantische Entsprechung von erweitert:If E is a non-nullable value type then the finally clause is expanded to the semantic equivalent of:

      finally {
          ((System.IDisposable)e).Dispose();
      }
      
    • Andernfalls wird die schließlich-Klausel auf die semantische Entsprechung von erweitert:Otherwise the finally clause is expanded to the semantic equivalent of:

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

    mit der Ausnahme E , dass bei einem Werttyp oder einem Typparameter, der auf einen Werttyp instanziiert e wird System.IDisposable , die Umwandlung von in nicht dazu führt, dass Boxing auftritt.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.

  • Andernfalls, wenn E ein versiegelter Typ ist, wird die letzte-Klausel auf einen leeren Block erweitert:Otherwise, if E is a sealed type, the finally clause is expanded to an empty block:

    finally {
    }
    
  • Andernfalls wird die schließlich-Klausel auf erweitert:Otherwise, the finally clause is expanded to:

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

    Die lokale Variable d ist für keinen Benutzercode sichtbar oder nicht verfügbar.The local variable d is not visible to or accessible to any user code. Dies hat insbesondere keinen Konflikt mit einer anderen Variablen, deren Bereich den letzten Block enthält.In particular, it does not conflict with any other variable whose scope includes the finally block.

Die Reihenfolge, foreach in der die Elemente eines Arrays durchlaufen werden, lautet wie folgt: Für eindimensionale Arrays werden Elemente in steigender Index Reihenfolge durchlaufen, beginnend mit 0 Index und endende Length - 1mit 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. Bei mehrdimensionalen Arrays werden Elemente so durchlaufen, dass die Indizes der äußersten rechten Dimension zuerst angehoben werden, dann die nächste linke Dimension usw.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.

Im folgenden Beispiel werden die einzelnen Werte in der Reihenfolge der Elemente in einem zweidimensionalen Array ausgegeben: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();
    }
}

Die erstellte Ausgabe lautet wie folgt:The output produced is as follows:

1.2 2.3 3.4 4.5 5.6 6.7 7.8 8.9

Im BeispielIn the example

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

der Typ von n wird als int, der Elementtyp von numbers, abgeleitet.the type of n is inferred to be int, the element type of numbers.

SprunganweisungenJump statements

Jump-Anweisungen: Bedingungs Übertragung der Steuerung.Jump statements unconditionally transfer control.

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

Der Speicherort, an den eine Jump-Anweisung die Steuerung überträgt, wird als Ziel der Jump-Anweisung bezeichnet.The location to which a jump statement transfers control is called the target of the jump statement.

Wenn eine Jump-Anweisung innerhalb eines-Blocks auftritt und sich das Ziel dieser Jump-Anweisung außerhalb dieses Blocks befindet, wird die Jump-Anweisung zum Beenden des Blocks bezeichnet.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. Während eine Jump-Anweisung die Steuerung von einem-Block übertragen kann, kann Sie die Steuerung niemals in einen-Block übertragen.While a jump statement may transfer control out of a block, it can never transfer control into a block.

Die Ausführung von Jump-Anweisungen wird durch das vorhanden sein try von dazwischenliegenden Anweisungen erschwert.Execution of jump statements is complicated by the presence of intervening try statements. Wenn solche try Anweisungen fehlen, überträgt eine Jump-Anweisung bedingungslos die Steuerung von der Jump-Anweisung an das Ziel.In the absence of such try statements, a jump statement unconditionally transfers control from the jump statement to its target. Wenn diese dazwischenliegenden try Anweisungen vorhanden sind, ist die Ausführung komplexer.In the presence of such intervening try statements, execution is more complex. Wenn die Jump-Anweisung einen oder mehrere try Blöcke mit zugeordneten finally Blöcken beendet, wird die Steuerung anfänglich an den finally Block der try innersten Anweisung übertragen.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. Wenn und wenn das Steuerelement den Endpunkt eines finally -Blocks erreicht, wird die Steuerung an den finally -Block der nächsten einschließenden try Anweisung übertragen.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. Dieser Vorgang wird wiederholt, finally bis die Blöcke aller try dazwischen liegenden Anweisungen ausgeführt wurden.This process is repeated until the finally blocks of all intervening try statements have been executed.

Im BeispielIn 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");
    }
}

die finally Blöcke, die zwei try Anweisungen zugeordnet sind, werden ausgeführt, bevor die Steuerung an das Ziel der Jump-Anweisung übertragen wird.the finally blocks associated with two try statements are executed before control is transferred to the target of the jump statement.

Die erstellte Ausgabe lautet wie folgt:The output produced is as follows:

Before break
Innermost finally block
Outermost finally block
After break

Die Break-AnweisungThe break statement

Die break -Anweisung beendet die nächste whileeinschließende do switch for-,- foreach ,-,-oder-Anweisung.The break statement exits the nearest enclosing switch, while, do, for, or foreach statement.

break_statement
    : 'break' ';'
    ;

Das break Ziel einer-Anweisung ist der Endpunkt der nächsten einschließenden switch, while, do for, oder foreach -Anweisung.The target of a break statement is the end point of the nearest enclosing switch, while, do, for, or foreach statement. Wenn eine break -Anweisung nicht durch eine switch-, while do for-,-, foreach -oder-Anweisung eingeschlossen ist, tritt ein Kompilierzeitfehler auf.If a break statement is not enclosed by a switch, while, do, for, or foreach statement, a compile-time error occurs.

Wenn mehrere switch- while foreach break , do-,-,-oder-Anweisungen ineinander geschachtelt sind, gilt eine-Anweisung nur für die innerste-Anweisung. forWhen multiple switch, while, do, for, or foreach statements are nested within each other, a break statement applies only to the innermost statement. Um die Steuerung auf mehrere Schachtelungs Ebenen goto zu übertragen, muss eine-Anweisung (die GoTo-Anweisung) verwendet werden.To transfer control across multiple nesting levels, a goto statement (The goto statement) must be used.

Eine break -Anweisung kann einen finally Block nicht beenden (try-Anweisung).A break statement cannot exit a finally block (The try statement). Wenn eine break -Anweisung innerhalb eines finally -Blocks auftritt break , muss sich das Ziel der-Anweisung innerhalb finally desselben-Blocks befinden; andernfalls tritt ein Kompilierzeitfehler auf.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.

Eine break -Anweisung wird wie folgt ausgeführt:A break statement is executed as follows:

  • Wenn die break Anweisung einen oder mehrere try Blöcke mit zugeordneten finally Blöcken beendet, wird die Steuerung anfänglich finally an den Block der innersten try Anweisung übertragen.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. Wenn und wenn das Steuerelement den Endpunkt eines finally -Blocks erreicht, wird die Steuerung an den finally -Block der nächsten einschließenden try Anweisung übertragen.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. Dieser Vorgang wird wiederholt, finally bis die Blöcke aller try dazwischen liegenden Anweisungen ausgeführt wurden.This process is repeated until the finally blocks of all intervening try statements have been executed.
  • Das Steuerelement wird an das Ziel der break -Anweisung übertragen.Control is transferred to the target of the break statement.

Da eine break Anweisung die Steuerung an andere Stellen überträgt, ist der Endpunkt break einer Anweisung nie erreichbar.Because a break statement unconditionally transfers control elsewhere, the end point of a break statement is never reachable.

Die Continue-AnweisungThe continue statement

Mit continue der-Anweisung wird eine neue Iterations Anweisung der nächsten while doeinschließenden for- foreach ,-,-oder-Anweisung gestartet.The continue statement starts a new iteration of the nearest enclosing while, do, for, or foreach statement.

continue_statement
    : 'continue' ';'
    ;

Das continue Ziel einer-Anweisung ist der Endpunkt der eingebetteten Anweisung der nächsten doeinschließenden while for-,-,-oder foreach -Anweisung.The target of a continue statement is the end point of the embedded statement of the nearest enclosing while, do, for, or foreach statement. Wenn eine continue -Anweisung nicht durch eine while-, do for-,- foreach oder-Anweisung eingeschlossen ist, tritt ein Kompilierzeitfehler auf.If a continue statement is not enclosed by a while, do, for, or foreach statement, a compile-time error occurs.

Wenn mehrere while- do foreach ,-,-oder-Anweisungen ineinander geschachtelt sind continue , gilt eine-Anweisung nur für die innerste-Anweisung. forWhen multiple while, do, for, or foreach statements are nested within each other, a continue statement applies only to the innermost statement. Um die Steuerung auf mehrere Schachtelungs Ebenen goto zu übertragen, muss eine-Anweisung (die GoTo-Anweisung) verwendet werden.To transfer control across multiple nesting levels, a goto statement (The goto statement) must be used.

Eine continue -Anweisung kann einen finally Block nicht beenden (try-Anweisung).A continue statement cannot exit a finally block (The try statement). Wenn eine continue -Anweisung innerhalb eines finally -Blocks auftritt continue , muss sich das Ziel der-Anweisung innerhalb finally desselben-Blocks befinden; andernfalls tritt ein Kompilierzeitfehler auf.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.

Eine continue -Anweisung wird wie folgt ausgeführt:A continue statement is executed as follows:

  • Wenn die continue Anweisung einen oder mehrere try Blöcke mit zugeordneten finally Blöcken beendet, wird die Steuerung anfänglich finally an den Block der innersten try Anweisung übertragen.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. Wenn und wenn das Steuerelement den Endpunkt eines finally -Blocks erreicht, wird die Steuerung an den finally -Block der nächsten einschließenden try Anweisung übertragen.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. Dieser Vorgang wird wiederholt, finally bis die Blöcke aller try dazwischen liegenden Anweisungen ausgeführt wurden.This process is repeated until the finally blocks of all intervening try statements have been executed.
  • Das Steuerelement wird an das Ziel der continue -Anweisung übertragen.Control is transferred to the target of the continue statement.

Da eine continue Anweisung die Steuerung an andere Stellen überträgt, ist der Endpunkt continue einer Anweisung nie erreichbar.Because a continue statement unconditionally transfers control elsewhere, the end point of a continue statement is never reachable.

Die goto-AnweisungThe goto statement

Mit goto der-Anweisung wird die Steuerung an eine Anweisung übertragen, die durch eine Bezeichnung gekennzeichnet ist.The goto statement transfers control to a statement that is marked by a label.

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

Das Ziel einer goto bezeichneranweisung ist die bezeichnete Anweisung mit der angegebenen Bezeichnung.The target of a goto identifier statement is the labeled statement with the given label. Wenn eine Bezeichnung mit dem angegebenen Namen nicht im aktuellen Funktionsmember vorhanden ist oder die goto Anweisung nicht innerhalb des Bereichs der Bezeichnung liegt, tritt ein Kompilierzeitfehler auf.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. Diese Regel ermöglicht die Verwendung einer goto -Anweisung, um die Steuerung aus einem nicht in einen Bereich eingefügten Bereich zu übertragen, jedoch nicht in einen eingefügten Bereich.This rule permits the use of a goto statement to transfer control out of a nested scope, but not into a nested scope. Im BeispielIn 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);
        }
    }
}

eine goto -Anweisung wird verwendet, um die Steuerung aus einem in einem Bereich befindlichen Bereich zu übertragen.a goto statement is used to transfer control out of a nested scope.

Das Ziel goto case einer-Anweisung ist die Anweisungs Liste in der unmittelbar switch einschließenden Anweisung (Switch-Anweisung), die case eine Bezeichnung mit dem angegebenen konstanten Wert enthält.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. , Wenn die goto case-Anweisung nicht durch eine switch-Anweisung eingeschlossen ist,, wenn die constant_expression nicht implizit konvertierbar ist (implizite Konvertierungen), in den regierenden Typ der nächstgelegenen switch-Anweisung oder, wenn die nächste einschließende switch-Anweisung enthält keine case-Bezeichnung mit dem angegebenen konstanten Wert. ein Kompilierzeitfehler tritt auf.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.

Das Ziel goto default einer-Anweisung ist die Anweisungs Liste in der unmittelbar switch einschließenden Anweisung (Switch-Anweisung), die default eine Bezeichnung enthält.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. Wenn die goto default Anweisung nicht durch eine switch -Anweisung eingeschlossen ist, oder wenn die nächste einschließende switch Anweisung keine default Bezeichnung enthält, tritt ein Kompilierzeitfehler auf.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.

Eine goto -Anweisung kann einen finally Block nicht beenden (try-Anweisung).A goto statement cannot exit a finally block (The try statement). Wenn eine goto -Anweisung innerhalb eines finally -Blocks auftritt goto , muss sich das Ziel der-Anweisung innerhalb finally desselben Blocks befinden, andernfalls tritt ein Kompilierzeitfehler auf.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.

Eine goto -Anweisung wird wie folgt ausgeführt:A goto statement is executed as follows:

  • Wenn die goto Anweisung einen oder mehrere try Blöcke mit zugeordneten finally Blöcken beendet, wird die Steuerung anfänglich finally an den Block der innersten try Anweisung übertragen.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. Wenn und wenn das Steuerelement den Endpunkt eines finally -Blocks erreicht, wird die Steuerung an den finally -Block der nächsten einschließenden try Anweisung übertragen.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. Dieser Vorgang wird wiederholt, finally bis die Blöcke aller try dazwischen liegenden Anweisungen ausgeführt wurden.This process is repeated until the finally blocks of all intervening try statements have been executed.
  • Das Steuerelement wird an das Ziel der goto -Anweisung übertragen.Control is transferred to the target of the goto statement.

Da eine goto Anweisung die Steuerung an andere Stellen überträgt, ist der Endpunkt goto einer Anweisung nie erreichbar.Because a goto statement unconditionally transfers control elsewhere, the end point of a goto statement is never reachable.

Return-AnweisungThe return statement

Die return -Anweisung gibt die Steuerung an den aktuellen Aufrufer der Funktion return zurück, in der die-Anweisung angezeigt wird.The return statement returns control to the current caller of the function in which the return statement appears.

return_statement
    : 'return' expression? ';'
    ;

Eine return -Anweisung ohne Ausdruck kann nur in einem Funktionsmember verwendet werden, der keinen Wert berechnet, d. h. eine Methode mit dem Ergebnistyp (Methoden Text) void, set der-Accessor einer Eigenschaft oder eines Indexers, der add - remove und-Accessoren eines Ereignisses, eines Instanzkonstruktors, eines statischen Konstruktors oder eines Dekonstruktors.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.

Eine return -Anweisung mit einem-Ausdruck kann nur in einem Funktionsmember verwendet werden, der einen-Wert berechnet, d. h. eine Methode mit einem nicht leeren get Ergebnistyp, den-Accessor einer Eigenschaft oder einen Indexer oder einen benutzerdefinierten Operator.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. Eine implizite Konvertierung (implizite Konvertierungen) muss vom Typ des Ausdrucks bis zum Rückgabetyp des enthaltenden Funktionsmembers vorhanden sein.An implicit conversion (Implicit conversions) must exist from the type of the expression to the return type of the containing function member.

Return-Anweisungen können auch im Text der anonymen Funktions Ausdrücke (Anonyme FunktionsAusdrücke) verwendet werden und daran beteiligt sein, zu bestimmen, welche Konvertierungen für diese Funktionen vorhanden sind.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.

Es handelt sich um einen Kompilierzeitfehler return , damit eine-Anweisung finally in einem-Block (der try-Anweisung) angezeigt wird.It is a compile-time error for a return statement to appear in a finally block (The try statement).

Eine return -Anweisung wird wie folgt ausgeführt:A return statement is executed as follows:

  • Wenn die return Anweisung einen Ausdruck angibt, wird der Ausdruck ausgewertet, und der resultierende Wert wird durch eine implizite Konvertierung in den Rückgabetyp der enthaltenden Funktion konvertiert.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. Das Ergebnis der Konvertierung wird der Ergebniswert, der von der-Funktion erzeugt wird.The result of the conversion becomes the result value produced by the function.
  • Wenn die return -Anweisung von einem oder mehreren try -oder catch -Blöcken mit finally zugeordneten-Blöcken eingeschlossen wird, wird finally die Steuerung anfänglich an try den-Block der innersten-Anweisung übertragen.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. Wenn und wenn das Steuerelement den Endpunkt eines finally -Blocks erreicht, wird die Steuerung an den finally -Block der nächsten einschließenden try Anweisung übertragen.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. Dieser Vorgang wird wiederholt, finally bis die Blöcke aller einschließenden try Anweisungen ausgeführt wurden.This process is repeated until the finally blocks of all enclosing try statements have been executed.
  • Wenn die enthaltende Funktion keine Async-Funktion ist, wird die Steuerung an den Aufrufer der enthaltenden Funktion zusammen mit dem Ergebniswert zurückgegeben, falls vorhanden.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.
  • Wenn die enthaltende Funktion eine Async-Funktion ist, wird die Steuerung an den aktuellen Aufrufer zurückgegeben, und der Ergebniswert wird ggf. in der Rückgabe Aufgabe aufgezeichnet, wie in (Enumeratorschnittstellen) beschrieben.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).

Da eine return Anweisung die Steuerung an andere Stellen überträgt, ist der Endpunkt return einer Anweisung nie erreichbar.Because a return statement unconditionally transfers control elsewhere, the end point of a return statement is never reachable.

Die throw-AnweisungThe throw statement

Die throw -Anweisung löst eine Ausnahme aus.The throw statement throws an exception.

throw_statement
    : 'throw' expression? ';'
    ;

Eine throw -Anweisung mit einem Ausdruck löst den Wert aus, der durch Auswerten des Ausdrucks erzeugt wird.A throw statement with an expression throws the value produced by evaluating the expression. Der Ausdruck muss einen Wert des Klassen Typs System.Exception, eines Klassen Typs, der von System.Exception abgeleitet ist System.Exception , oder von einem typparametertyp mit (oder einer Unterklasse) als effektive Basisklasse bezeichnen.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. Wenn die Auswertung des Ausdrucks erzeugt null, wird System.NullReferenceException stattdessen eine ausgelöst.If evaluation of the expression produces null, a System.NullReferenceException is thrown instead.

Eine throw -Anweisung ohne Ausdruck kann nur in einem catch -Block verwendet werden. in diesem Fall löst die-Anweisung die Ausnahme erneut aus, die zurzeit von catch diesem Block behandelt wird.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.

Da eine throw Anweisung die Steuerung an andere Stellen überträgt, ist der Endpunkt throw einer Anweisung nie erreichbar.Because a throw statement unconditionally transfers control elsewhere, the end point of a throw statement is never reachable.

Wenn eine Ausnahme ausgelöst wird, wird die Steuerung an die erste catch Klausel in einer einschließenden try Anweisung übertragen, die die Ausnahme behandeln kann.When an exception is thrown, control is transferred to the first catch clause in an enclosing try statement that can handle the exception. Der Prozess, der ab dem Zeitpunkt der Ausnahme ausgelöst wird, der zum Zeitpunkt der Übertragung der Steuerung an einen geeigneten Ausnahmehandler ausgelöst wird, wird als AusnahmeWeitergabe bezeichnet.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. Die Weitergabe einer Ausnahme besteht aus dem wiederholten Auswerten der folgenden catch Schritte, bis eine Klausel gefunden wird, die der Ausnahme entspricht.Propagation of an exception consists of repeatedly evaluating the following steps until a catch clause that matches the exception is found. In dieser Beschreibung ist der throw-Punkt anfänglich der Speicherort, an dem die Ausnahme ausgelöst wird.In this description, the throw point is initially the location at which the exception is thrown.

  • Im aktuellen Funktionsmember wird jede try Anweisung, die den Throw-Punkt einschließt, untersucht.In the current function member, each try statement that encloses the throw point is examined. Für jede Anweisung S, beginnend mit der innersten try -Anweisung und mit der äußersten try -Anweisung, werden die folgenden Schritte ausgewertet:For each statement S, starting with the innermost try statement and ending with the outermost try statement, the following steps are evaluated:

    • Wenn der try -Block S von den Throw-Punkt einschließt und S über eine oder mehrere catch Klauseln verfügt, catch werden die Klauseln in der Reihenfolge der Darstellung untersucht, um nach einem geeigneten Handler für die Ausnahme zu suchen. Dies erfolgt gemäß den in Abschnitt die try-Anweisung.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. Wenn eine überein catch stimmende Klausel gefunden wird, wird die Ausnahme Weitergabe durch übertragen der Steuerung an catch den Block dieser Klausel abgeschlossen.If a matching catch clause is located, the exception propagation is completed by transferring control to the block of that catch clause.

    • Andernfalls wird die Steuerung try an den S finally S catch -finally Block übertragen, wenn der-Block oder ein-Block den Throw-Punkt einschließt und wenn über einen-Block verfügt.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. Wenn der finally -Block eine andere Ausnahme auslöst, wird die Verarbeitung der aktuellen Ausnahme beendet.If the finally block throws another exception, processing of the current exception is terminated. Andernfalls wird die Verarbeitung der aktuellen Ausnahme fortgesetzt, finally wenn die Steuerung den Endpunkt des Blocks erreicht.Otherwise, when control reaches the end point of the finally block, processing of the current exception is continued.

  • Wenn ein Ausnahmehandler im aktuellen Funktionsaufruf nicht gefunden wurde, wird der Funktionsaufruf beendet, und eine der folgenden Aktionen wird ausgeführt:If an exception handler was not located in the current function invocation, the function invocation is terminated, and one of the following occurs:

    • Wenn die aktuelle Funktion nicht Async ist, werden die obigen Schritte für den Aufrufer der Funktion mit einem Throw-Punkt wiederholt, der der Anweisung entspricht, aus der der Funktionsmember aufgerufen wurde.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.

    • Wenn die aktuelle Funktion Async ist und die Aufgabe zurückgibt, wird die Ausnahme in der Rückgabe Aufgabe aufgezeichnet, die in einen fehlerhaften oder abgebrochenen Zustand versetzt wird, wie in Enumeratorschnittstellenbeschrieben.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.

    • Wenn die aktuelle Funktion Async ist und void zurückgibt, wird der Synchronisierungs Kontext des aktuellen Threads wie in Aufzähl baren Schnittstellenbeschrieben benachrichtigt.If the current function is async and void-returning, the synchronization context of the current thread is notified as described in Enumerable interfaces.

  • Wenn die Ausnahme Verarbeitung alle Funktionselement Aufrufe im aktuellen Thread beendet und angibt, dass der Thread keinen Handler für die Ausnahme aufweist, wird der Thread selbst beendet.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. Die Auswirkungen dieser Beendigung sind Implementierungs definiert.The impact of such termination is implementation-defined.

Die try-AnweisungThe try statement

Die try -Anweisung stellt einen Mechanismus zum Abfangen von Ausnahmen bereit, die während der Ausführung eines-Blocks auftreten.The try statement provides a mechanism for catching exceptions that occur during execution of a block. Außerdem bietet die try -Anweisung die Möglichkeit, einen Codeblock anzugeben, der immer ausgeführt wird, wenn das Steuer try Element die-Anweisung verlässt.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
    ;

Es gibt drei mögliche Formen von try -Anweisungen:There are three possible forms of try statements:

  • Ein try -Block, gefolgt von einem catch oder mehreren-Blöcken.A try block followed by one or more catch blocks.
  • Ein try -Block, gefolgt finally von einem-Block.A try block followed by a finally block.
  • Ein try -Block, gefolgt von einem catch oder mehreren-Blöcken finally , gefolgt von einem-Block.A try block followed by one or more catch blocks followed by a finally block.

Wenn eine catch-Klausel ein exception_specifier-Element angibt, muss der Typ System.Exception, ein Typ, der von System.Exception abgeleitet ist, oder ein typparametertyp sein, der über System.Exception (oder eine Unterklasse) als effektive Basisklasse verfügt.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.

Wenn eine catch-Klausel sowohl eine exception_specifier mit einem Bezeichnerangibt, wird eine Ausnahme Variable mit dem angegebenen Namen und Typ deklariert.When a catch clause specifies both an exception_specifier with an identifier, an exception variable of the given name and type is declared. Die Exception-Variable entspricht einer lokalen Variablen mit einem Bereich, der die catch -Klausel erweitert.The exception variable corresponds to a local variable with a scope that extends over the catch clause. Während der Ausführung des exception_filter und des Blocksstellt die Ausnahme Variable die derzeit behandelte Ausnahme dar.During execution of the exception_filter and block, the exception variable represents the exception currently being handled. Zum Zweck der eindeutigen Zuweisungs Überprüfung wird die Ausnahme Variable als definitiv in Ihrem gesamten Bereich zugewiesen.For purposes of definite assignment checking, the exception variable is considered definitely assigned in its entire scope.

Es ist catch nicht möglich, auf das Ausnahme Objekt im Filter und catch Block zuzugreifen, es sei denn, eine Klausel enthält einen Ausnahme Variablennamen.Unless a catch clause includes an exception variable name, it is impossible to access the exception object in the filter and catch block.

Eine catch-Klausel, die keine exception_specifier angibt, wird als allgemeine catch-Klausel bezeichnet.A catch clause that does not specify an exception_specifier is called a general catch clause.

Einige Programmiersprachen unterstützen möglicherweise Ausnahmen, die nicht als von System.Exceptionabgeleitete Objekt darstellbar sind, obwohl solche Ausnahmen nie durch C# Code generiert werden könnten.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. Eine allgemeine catch Klausel kann verwendet werden, um solche Ausnahmen abzufangen.A general catch clause may be used to catch such exceptions. Daher unterscheidet sich catch eine allgemeine Klausel semantisch von einer, die den Typ System.Exceptionangibt, da der erste auch Ausnahmen von anderen Sprachen abfängt.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.

Um einen Handler für eine Ausnahme zu finden, catch werden Klauseln in lexikalischer Reihenfolge untersucht.In order to locate a handler for an exception, catch clauses are examined in lexical order. Wenn eine catch Klausel einen Typ, aber keinen Ausnahme Filter angibt, ist dies ein Kompilierzeitfehler für eine catch spätere Klausel in derselben try Anweisung, um einen Typ anzugeben, der dem Typ entspricht oder von diesem abgeleitet ist.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. Wenn eine catch Klausel keinen Typ und keinen Filter angibt, muss es sich um die catch letzte Klausel für try diese Anweisung handeln.If a catch clause specifies no type and no filter, it must be the last catch clause for that try statement.

Innerhalb eines catch -Blocks kann throw eine-Anweisung (die throw-Anweisung) ohne Ausdruck verwendet werden, um catch die vom-Block aufgefangene Ausnahme erneut auszulösen.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. Bei Zuweisungen zu einer Ausnahme Variablen wird die Ausnahme, die erneut ausgelöst wird, nicht geändert.Assignments to an exception variable do not alter the exception that is re-thrown.

Im BeispielIn 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);
        }
    }
}

die Methode F fängt eine Ausnahme ab, schreibt einige Diagnoseinformationen in die Konsole, ändert die Ausnahme Variable und löst die Ausnahme erneut aus.the method F catches an exception, writes some diagnostic information to the console, alters the exception variable, and re-throws the exception. Die Ausnahme, die erneut ausgelöst wird, ist die ursprüngliche Ausnahme, sodass die Ausgabe erzeugt wird:The exception that is re-thrown is the original exception, so the output produced is:

Exception in F: G
Exception in Main: G

Wenn der erste catch-Block e ausgelöst wurde und die aktuelle Ausnahme nicht erneut ausgelöst wurde, sieht die Ausgabe wie folgt aus: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

Es handelt sich um einen Kompilierzeitfehler breakfür continueeine- goto ,-oder-Anweisung zum über finally tragen der Steuerung aus einem-Block.It is a compile-time error for a break, continue, or goto statement to transfer control out of a finally block. Wenn eine break- continue,- goto oder-Anweisung in finally einem-Block auftritt, muss sich das Ziel der-Anweisung finally innerhalb desselben Blocks befinden. andernfalls tritt ein Kompilierzeitfehler auf.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.

Es handelt sich um einen Kompilierzeitfehler return , damit eine-Anweisung finally in einem-Block auftritt.It is a compile-time error for a return statement to occur in a finally block.

Eine try -Anweisung wird wie folgt ausgeführt:A try statement is executed as follows:

  • Das Steuerelement wird an try den-Block übertragen.Control is transferred to the try block.

  • Wenn und wenn das Steuerelement den Endpunkt des try Blocks erreicht:When and if control reaches the end point of the try block:

    • Wenn die try Anweisung über einen finally -Block verfügt finally , wird der-Block ausgeführt.If the try statement has a finally block, the finally block is executed.
    • Das Steuerelement wird an den Endpunkt try der Anweisung übertragen.Control is transferred to the end point of the try statement.
  • Wenn eine Ausnahme während der Ausführung try try des Blocks an die Anweisung weitergegeben wird:If an exception is propagated to the try statement during execution of the try block:

    • Die catch Klauseln werden ggf. in der Reihenfolge ihrer Darstellung untersucht, um einen geeigneten Handler für die Ausnahme zu suchen.The catch clauses, if any, are examined in order of appearance to locate a suitable handler for the exception. Wenn eine catch -Klausel keinen Typ angibt oder den Ausnahmetyp oder einen Basistyp des Ausnahme Typs angibt:If a catch clause does not specify a type, or specifies the exception type or a base type of the exception type:
      • Wenn die catch -Klausel eine Exception-Variable deklariert, wird das Ausnahme Objekt der Ausnahme Variablen zugewiesen.If the catch clause declares an exception variable, the exception object is assigned to the exception variable.
      • Wenn die catch -Klausel einen Ausnahme Filter deklariert, wird der Filter ausgewertet.If the catch clause declares an exception filter, the filter is evaluated. Wenn ausgewertet falsewird, ist die catch-Klausel keine Entsprechung, und die Suche wird durch alle nachfolg catch enden Klauseln für einen geeigneten Handler fortgesetzt.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.
      • Andernfalls wird die catch -Klausel als Übereinstimmung angesehen, und die Steuerung wird an den catch entsprechenden-Block übertragen.Otherwise, the catch clause is considered a match, and control is transferred to the matching catch block.
      • Wenn und wenn das Steuerelement den Endpunkt des catch Blocks erreicht:When and if control reaches the end point of the catch block:
        • Wenn die try Anweisung über einen finally -Block verfügt finally , wird der-Block ausgeführt.If the try statement has a finally block, the finally block is executed.
        • Das Steuerelement wird an den Endpunkt try der Anweisung übertragen.Control is transferred to the end point of the try statement.
      • Wenn eine Ausnahme während der Ausführung try catch des Blocks an die Anweisung weitergegeben wird:If an exception is propagated to the try statement during execution of the catch block:
        • Wenn die try Anweisung über einen finally -Block verfügt finally , wird der-Block ausgeführt.If the try statement has a finally block, the finally block is executed.
        • Die Ausnahme wird an die nächste einschließende try Anweisung weitergegeben.The exception is propagated to the next enclosing try statement.
    • Wenn die try Anweisung keine catch Klauseln aufweist oder wenn keine catch Klausel mit der Ausnahme übereinstimmt:If the try statement has no catch clauses or if no catch clause matches the exception:
      • Wenn die try Anweisung über einen finally -Block verfügt finally , wird der-Block ausgeführt.If the try statement has a finally block, the finally block is executed.
      • Die Ausnahme wird an die nächste einschließende try Anweisung weitergegeben.The exception is propagated to the next enclosing try statement.

Die-Anweisungen eines finally -Blocks werden immer ausgeführt, wenn die try Steuerung eine-Anweisung verlässt.The statements of a finally block are always executed when control leaves a try statement. Dies gilt unabhängig davon, ob die Steuerung aufgrund der normalen Ausführung breakaufgrund der Ausführung einer- goto, continue-,-oder return -Anweisung oder als Ergebnis der Weitergabe einer Ausnahme aus der try an.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.

Wenn während der Ausführung finally eines-Blocks eine Ausnahme ausgelöst wird und nicht innerhalb desselben letzten Blocks abgefangen wird, wird die Ausnahme an die nächste einschließende try Anweisung weitergegeben.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. Wenn eine andere Ausnahme gerade weitergegeben wurde, geht diese Ausnahme verloren.If another exception was in the process of being propagated, that exception is lost. Der Prozess der Weitergabe einer Ausnahme wird weiter unten in der Beschreibung der throw Anweisung (der throw-Anweisung) erläutert.The process of propagating an exception is discussed further in the description of the throw statement (The throw statement).

Der try -Block einer try -Anweisung ist erreichbar, try wenn die-Anweisung erreichbar ist.The try block of a try statement is reachable if the try statement is reachable.

Ein catch Block try einer-Anweisung ist erreichbar, wenn die-Anweisung erreichbar ist. tryA catch block of a try statement is reachable if the try statement is reachable.

Der finally -Block einer try -Anweisung ist erreichbar, try wenn die-Anweisung erreichbar ist.The finally block of a try statement is reachable if the try statement is reachable.

Der Endpunkt einer try -Anweisung ist erreichbar, wenn beide der folgenden Punkte zutreffen:The end point of a try statement is reachable if both of the following are true:

  • Der Endpunkt des try Blocks ist erreichbar, oder der Endpunkt von mindestens einem catch Block ist erreichbar.The end point of the try block is reachable or the end point of at least one catch block is reachable.
  • Wenn ein finally -Block vorhanden ist, ist der Endpunkt finally des-Blocks erreichbar.If a finally block is present, the end point of the finally block is reachable.

Die aktivierten und deaktivierten AnweisungenThe checked and unchecked statements

Die checked - unchecked und-Anweisungen werden verwendet, um den Überlauf Überprüfungs Kontext für arithmetische Operationen im ganzzahligen Typ und Konvertierungen zu steuern.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
    ;

Die checked -Anweisung bewirkt, dass alle Ausdrücke im- Block in einem überprüften Kontext ausgewertet werden unchecked , und die-Anweisung bewirkt, dass alle Ausdrücke im Block in einem nicht überprüften Kontext ausgewertet werden.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.

Die checked - unchecked und-Anweisungen entsprechen genau den checked Operatoren und (die aktivierten und deaktiviertenOperatoren), mit dem Unterschied, dass Sie anstelle von Ausdrücken an- unchecked Blöcken arbeiten.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.

Die Lock-AnweisungThe lock statement

Die lock -Anweisung ruft die Sperre für den gegenseitigen Ausschluss für ein bestimmtes Objekt ab, führt eine-Anweisung aus und gibt dann die Sperre frei.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
    ;

Der Ausdruck einer lock-Anweisung muss einen Wert eines Typs bezeichnen, der bekanntermaßen reference_typeist.The expression of a lock statement must denote a value of a type known to be a reference_type. Für den Ausdruck einer lock-Anweisung wird nie eine implizite Boxing-Konvertierung (Boxing-Konvertierungen) ausgeführt, und daher ist es ein Kompilierzeitfehler, wenn der Ausdruck den Wert eines value_typeangibt.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.

Eine lock -Anweisung der FormA lock statement of the form

lock (x) ...

Wenn x ein Ausdruck eines reference_typeist, ist genau Äquivalent zuwhere 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);
}

außer dass x nur einmal überprüft wird.except that x is only evaluated once.

Während eine gegenseitige Ausschluss Sperre aufrechterhalten wird, kann der Code, der im selben Ausführungs Thread ausgeführt wird, auch die Sperre abrufen und freigeben.While a mutual-exclusion lock is held, code executing in the same execution thread can also obtain and release the lock. Der Code, der in anderen Threads ausgeführt wird, wird jedoch blockiert, bis die Sperre aufgehoben wird.However, code executing in other threads is blocked from obtaining the lock until the lock is released.

Das System.Type Sperren von Objekten, um den Zugriff auf statische Daten zu synchronisieren, wird nicht empfohlen.Locking System.Type objects in order to synchronize access to static data is not recommended. Anderer Code kann denselben Typ sperren, was zu einem Deadlock führen kann.Other code might lock on the same type, which can result in deadlock. Ein besserer Ansatz besteht darin, den Zugriff auf statische Daten zu synchronisieren, indem ein privates statisches Objekt gesperrt wird.A better approach is to synchronize access to static data by locking a private static object. Zum Beispiel: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) {
            ...
        }
    }
}

Die using-AnweisungThe using statement

Die using -Anweisung ruft eine oder mehrere Ressourcen ab, führt eine-Anweisung aus und verwirft dann die 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
    ;

Eine Ressource ist eine Klasse oder Struktur, die System.IDisposableimplementiert, die eine einzelne Parameter lose Methode namens Disposeenthält.A resource is a class or struct that implements System.IDisposable, which includes a single parameterless method named Dispose. Code, der eine Ressource verwendet, kann Dispose aufzurufen, um anzugeben, dass die Ressource nicht mehr benötigt wird.Code that is using a resource can call Dispose to indicate that the resource is no longer needed. Wenn Dispose nicht aufgerufen wird, wird die automatische Entfernung schließlich aufgrund Garbage Collection ausgelöst.If Dispose is not called, then automatic disposal eventually occurs as a consequence of garbage collection.

Wenn die Form von resource_acquisition local_variable_declaration ist, muss der Typ des local_variable_declaration entweder dynamic oder ein Typ sein, der implizit in System.IDisposable konvertiert werden kann.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. Wenn die Form von resource_acquisition Expression ist, muss dieser Ausdruck implizit in System.IDisposable konvertiert werden können.If the form of resource_acquisition is expression then this expression must be implicitly convertible to System.IDisposable.

Lokale Variablen, die in einem resource_acquisition deklariert werden, sind schreibgeschützt und müssen einen Initialisierer enthalten.Local variables declared in a resource_acquisition are read-only, and must include an initializer. Ein Kompilierzeitfehler tritt auf, wenn die eingebettete Anweisung versucht, diese lokalen Variablen (über die ++ -und-Operatoren) zu ändern, die Adresse dieser Variablen zu ref über out nehmen oder Sie als-oder- -- Parameter zu übergeben.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.

Eine using -Anweisung wird in drei Teile übersetzt: Beschaffung, Verwendung und Entsorgung.A using statement is translated into three parts: acquisition, usage, and disposal. Die Verwendung der Ressource ist implizit in eine try -Anweisung eingeschlossen, die eine finally -Klausel einschließt.Usage of the resource is implicitly enclosed in a try statement that includes a finally clause. Diese finally Klausel verwirft die Ressource.This finally clause disposes of the resource. Wenn eine null Ressource Dispose abgerufen wird, wird kein-Rückruf durchgeführt, und es wird keine Ausnahme ausgelöst.If a null resource is acquired, then no call to Dispose is made, and no exception is thrown. Wenn die Ressource vom Typ dynamic ist, wird Sie dynamisch durch eine implizite dynamische Konvertierung (implizite dynamische IDisposable Konvertierungen) in in den Erwerb konvertiert, um sicherzustellen, dass die Konvertierung erfolgreich war, bevor die Verwendung und Ihnen.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.

Eine using -Anweisung der FormA using statement of the form

using (ResourceType resource = expression) statement

entspricht einer von drei möglichen Erweiterungen.corresponds to one of three possible expansions. Wenn ResourceType ein Werttyp ist, der keine NULL-Werte zulässt, ist die ErweiterungWhen ResourceType is a non-nullable value type, the expansion is

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

Andernfalls: Wenn ResourceType ein Werte zulässt-Werttyp oder ein anderer Verweistyp dynamicals ist, wird die ErweiterungOtherwise, 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();
    }
}

Andernfalls ist die ResourceType Erweiterung dynamic, wenn den Wert hat.Otherwise, when ResourceType is dynamic, the expansion is

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

Bei beiden Erweiterungen ist die resource -Variable in der eingebetteten-Anweisung schreibgeschützt, d und die-Variable ist in der eingebetteten-Anweisung nicht verfügbar, und Sie ist nicht sichtbar.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.

Eine Implementierung darf eine angegebene using-Anweisung anders implementieren, z. b. aus Leistungsgründen, solange das Verhalten mit der obigen Erweiterung konsistent ist.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.

Eine using -Anweisung der FormA using statement of the form

using (expression) statement

hat dieselben drei möglichen Erweiterungen.has the same three possible expansions. In diesem Fall ResourceType ist implizit der Kompilier Zeittyp expressionvon, wenn er über einen verfügt.In this case ResourceType is implicitly the compile-time type of the expression, if it has one. Andernfalls wird die IDisposable -Schnittstelle selbst ResourceTypeals verwendet.Otherwise the interface IDisposable itself is used as the ResourceType. Auf resource die-Variable kann nicht zugegriffen werden, und die eingebettete-Anweisung ist unsichtbar.The resource variable is inaccessible in, and invisible to, the embedded statement.

Wenn ein resource_acquisition das Format eines local_variable_declarationannimmt, ist es möglich, mehrere Ressourcen eines bestimmten Typs zu erhalten.When a resource_acquisition takes the form of a local_variable_declaration, it is possible to acquire multiple resources of a given type. Eine using -Anweisung der FormA using statement of the form

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

entspricht genau einer Sequenz von using -Anweisungen:is precisely equivalent to a sequence of nested using statements:

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

Im folgenden Beispiel wird eine Datei mit log.txt dem Namen erstellt, und es werden zwei Textzeilen in die Datei geschrieben.The example below creates a file named log.txt and writes two lines of text to the file. Im Beispiel wird dann dieselbe Datei zum Lesen geöffnet, und die enthaltenen Textzeilen werden in die Konsole kopiert.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);
            }

        }
    }
}

Da die TextWriter Klassen TextReader und die IDisposable -Schnittstelle implementieren, kann im using Beispiel-Anweisungen verwendet werden, um sicherzustellen, dass die zugrunde liegende Datei nach den Schreib-oder Lesevorgängen ordnungsgemäß geschlossen wirdSince 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.

Die yield-AnweisungThe yield statement

Die yield -Anweisung wird in einem Iteratorblock (Blocks) verwendet, um einen Wert für das Enumeratorobjekt (Enumeratorobjekte) oder das Aufzähl Bare Objekt (Aufzähl Bare Objekte) eines Iterators oder das Ende der Iterationen anzugeben.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' ';'
    ;

yieldist kein reserviertes Wort. Sie hat nur dann eine besondere Bedeutung, wenn Sie return direkt break vor einem Schlüsselwort oder verwendet wird.yield is not a reserved word; it has special meaning only when used immediately before a return or break keyword. In anderen Kontexten yield kann als Bezeichner verwendet werden.In other contexts, yield can be used as an identifier.

Es gibt mehrere Einschränkungen hinsichtlich des Orts yield , an dem eine-Anweisung angezeigt werden kann, wie im folgenden beschrieben.There are several restrictions on where a yield statement can appear, as described in the following.

  • Es handelt sich um einen Kompilierzeitfehler für eine yield-Anweisung (von beiden Formularen), die außerhalb von method_body, operator_body oder accessor_body angezeigt wird.It is a compile-time error for a yield statement (of either form) to appear outside a method_body, operator_body or accessor_body
  • Es handelt sich um einen Kompilierzeitfehler yield für eine-Anweisung (von beiden Formularen), die in einer anonymen Funktion angezeigt wird.It is a compile-time error for a yield statement (of either form) to appear inside an anonymous function.
  • Es handelt sich um einen Kompilierzeitfehler yield für eine-Anweisung (von beiden Formularen), finally die in der try -Klausel einer-Anweisung angezeigt wird.It is a compile-time error for a yield statement (of either form) to appear in the finally clause of a try statement.
  • Es ist ein Kompilierzeitfehler, wenn yield return eine-Anweisung an einer beliebigen try Stelle in einer- catch Anweisung angezeigt wird, die Klauseln enthält.It is a compile-time error for a yield return statement to appear anywhere in a try statement that contains any catch clauses.

Das folgende Beispiel zeigt einige gültige und ungültige Verwendungen von yield -Anweisungen.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
}

Eine implizite Konvertierung (implizite Konvertierungen) muss vom Typ des Ausdrucks in der yield return -Anweisung bis zum Yield-Typ (Yield-Typ) des Iterators vorhanden sein.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.

Eine yield return -Anweisung wird wie folgt ausgeführt:A yield return statement is executed as follows:

  • Der in der-Anweisung angegebene Ausdruck wird ausgewertet, implizit in den Yield-Typ konvertiert und der Current -Eigenschaft des Enumeratorobjekts zugewiesen.The expression given in the statement is evaluated, implicitly converted to the yield type, and assigned to the Current property of the enumerator object.
  • Die Ausführung des Iteratorblocks wurde angehalten.Execution of the iterator block is suspended. Wenn sich yield return die-Anweisung innerhalb eines oder try mehrerer Blöcke befindet, finally werden die zugeordneten Blöcke zurzeit nicht ausgeführt.If the yield return statement is within one or more try blocks, the associated finally blocks are not executed at this time.
  • Die MoveNext -Methode des Enumeratorobjekts wird true an den Aufrufer zurückgegeben und gibt an, dass das Enumeratorobjekt erfolgreich auf das nächste Element erweitert wurde.The MoveNext method of the enumerator object returns true to its caller, indicating that the enumerator object successfully advanced to the next item.

Der nächste aufrufungs Vorgang der- MoveNext Methode des Enumeratorobjekts setzt die Ausführung des Iteratorblocks fort, von wo er zuletzt angehalten wurde.The next call to the enumerator object's MoveNext method resumes execution of the iterator block from where it was last suspended.

Eine yield break -Anweisung wird wie folgt ausgeführt:A yield break statement is executed as follows:

  • Wenn die yield break -Anweisung von einem oder mehreren try -Blöcken mit zugeordneten finally -Blöcken eingeschlossen wird, wird die finally Steuerung anfänglich an den try -Block der innersten-Anweisung übertragen.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. Wenn und wenn das Steuerelement den Endpunkt eines finally -Blocks erreicht, wird die Steuerung an den finally -Block der nächsten einschließenden try Anweisung übertragen.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. Dieser Vorgang wird wiederholt, finally bis die Blöcke aller einschließenden try Anweisungen ausgeführt wurden.This process is repeated until the finally blocks of all enclosing try statements have been executed.
  • Das Steuerelement wird an den Aufrufer des Iteratorblocks zurückgegeben.Control is returned to the caller of the iterator block. Dies ist entweder die MoveNext -Methode Dispose oder die-Methode des Enumeratorobjekts.This is either the MoveNext method or Dispose method of the enumerator object.

Da eine yield break Anweisung die Steuerung an andere Stellen überträgt, ist der Endpunkt yield break einer Anweisung nie erreichbar.Because a yield break statement unconditionally transfers control elsewhere, the end point of a yield break statement is never reachable.