InstrukcjeStatements

Język C# zawiera różne instrukcje.C# provides a variety of statements. Większość z tych instrukcji będzie znana deweloperom, którzy zaprogramowany w C i C++.Most of these statements will be familiar to developers who have programmed in C and C++.

statement
    : labeled_statement
    | declaration_statement
    | embedded_statement
    ;

embedded_statement
    : block
    | empty_statement
    | expression_statement
    | selection_statement
    | iteration_statement
    | jump_statement
    | try_statement
    | checked_statement
    | unchecked_statement
    | lock_statement
    | using_statement
    | yield_statement
    | embedded_statement_unsafe
    ;

Embedded_statement niebędący terminalem jest używany dla instrukcji, które są wyświetlane w innych instrukcjach.The embedded_statement nonterminal is used for statements that appear within other statements. Użycie embedded_statement zamiast instrukcji wyklucza użycie instrukcji deklaracji oraz instrukcji oznaczonych etykietami w tych kontekstach.The use of embedded_statement rather than statement excludes the use of declaration statements and labeled statements in these contexts. PrzykładThe example

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

powoduje błąd czasu kompilacji, ponieważ if instrukcja wymaga embedded_statement , a nie instrukcji dla jego gałęzi IF.results in a compile-time error because an if statement requires an embedded_statement rather than a statement for its if branch. Jeśli ten kod był dozwolony, zmienna i zostałaby zadeklarowana, ale nigdy nie można jej użyć.If this code were permitted, then the variable i would be declared, but it could never be used. Należy jednak pamiętać, że przez umieszczenie i deklaracji w bloku, przykład jest prawidłowy.Note, however, that by placing i's declaration in a block, the example is valid.

Punkty końcowe i osiągalnośćEnd points and reachability

Każda instrukcja ma punkt końcowy.Every statement has an end point. W intuicyjnych warunkach punkt końcowy instrukcji jest lokalizacją, która jest bezpośrednio zgodna z instrukcją.In intuitive terms, the end point of a statement is the location that immediately follows the statement. Reguły wykonywania dla złożonych instrukcji (Instrukcje zawierające osadzone instrukcje) określają akcję, która jest wykonywana, gdy kontrolka osiągnie punkt końcowy osadzonej instrukcji.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. Na przykład, gdy formant osiągnie punkt końcowy instrukcji w bloku, formant jest przenoszony do następnej instrukcji w bloku.For example, when control reaches the end point of a statement in a block, control is transferred to the next statement in the block.

Jeśli instrukcja może zostać osiągnięta przez wykonanie, instrukcja jest określana jako *osiągalna _.If a statement can possibly be reached by execution, the statement is said to be *reachable _. Z drugiej strony, jeśli nie ma możliwości wykonania instrukcji, instrukcja jest określana jako _ nieosiągalny *.Conversely, if there is no possibility that a statement will be executed, the statement is said to be _*unreachable**.

W przykładzieIn the example

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

drugie wywołanie Console.WriteLine jest nieosiągalne, ponieważ nie ma możliwości wykonania instrukcji.the second invocation of Console.WriteLine is unreachable because there is no possibility that the statement will be executed.

Ostrzeżenie jest zgłaszane, gdy kompilator ustali, że instrukcja jest nieosiągalna.A warning is reported if the compiler determines that a statement is unreachable. Nie jest to błąd, aby instrukcja była nieosiągalna.It is specifically not an error for a statement to be unreachable.

Aby określić, czy dana instrukcja lub punkt końcowy są osiągalne, kompilator wykonuje analizę przepływu zgodnie z regułami osiągalności określonymi dla każdej instrukcji.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. Analiza przepływu uwzględnia wartości wyrażeń stałych (wyrażeń stałych) kontrolujących zachowanie instrukcji, ale nie są brane pod uwagę możliwe wartości wyrażeń niestałych.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. Innymi słowy, w celach analizy przepływu sterowania, niestałe wyrażenie danego typu jest uznawane za ma dowolną możliwą wartość tego typu.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.

W przykładzieIn the example

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

wyrażenie logiczne if instrukcji jest wyrażeniem stałym, ponieważ oba operandy == operatora są stałymi.the boolean expression of the if statement is a constant expression because both operands of the == operator are constants. Ponieważ wyrażenie stałe jest oceniane w czasie kompilacji, przez wygenerowanie wartości false , Console.WriteLine wywołanie jest uznawane za nieosiągalne.As the constant expression is evaluated at compile-time, producing the value false, the Console.WriteLine invocation is considered unreachable. Jeśli jednak i zostanie zmieniony jako zmienna lokalnaHowever, if i is changed to be a local variable

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

Console.WriteLinewywołanie jest uznawane za osiągalne, mimo że w rzeczywistości nigdy nie zostanie wykonane.the Console.WriteLine invocation is considered reachable, even though, in reality, it will never be executed.

Blok składowej funkcji jest zawsze uznawany za osiągalny.The block of a function member is always considered reachable. Poprzez dokonanie oceny reguł osiągalności każdej instrukcji w bloku, można określić osiągalność każdej z tych instrukcji.By successively evaluating the reachability rules of each statement in a block, the reachability of any given statement can be determined.

W przykładzieIn the example

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

osiągalność sekundy Console.WriteLine jest określana w następujący sposób:the reachability of the second Console.WriteLine is determined as follows:

  • Pierwsza Console.WriteLine Instrukcja wyrażenia jest osiągalna, ponieważ blok F metody jest osiągalny.The first Console.WriteLine expression statement is reachable because the block of the F method is reachable.
  • Punkt końcowy pierwszej Console.WriteLine instrukcji wyrażenia jest osiągalny, ponieważ ta instrukcja jest osiągalna.The end point of the first Console.WriteLine expression statement is reachable because that statement is reachable.
  • ifInstrukcja jest osiągalna, ponieważ punkt końcowy pierwszej Console.WriteLine instrukcji wyrażenia jest osiągalny.The if statement is reachable because the end point of the first Console.WriteLine expression statement is reachable.
  • Druga Console.WriteLine Instrukcja wyrażenia jest osiągalna, ponieważ wyrażenie logiczne instrukcji nie if ma stałej wartości false .The second Console.WriteLine expression statement is reachable because the boolean expression of the if statement does not have the constant value false.

Istnieją dwie sytuacje, w których jest to błąd czasu kompilacji dla punktu końcowego instrukcji, aby uzyskać dostęp:There are two situations in which it is a compile-time error for the end point of a statement to be reachable:

  • Ponieważ switch instrukcja nie zezwala sekcji Switch na "przechodzenie" do następnej sekcji Switch, jest to błąd czasu kompilacji dla punktu końcowego listy instrukcji przełącznika, aby uzyskać dostęp.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. W przypadku wystąpienia tego błędu jest to zazwyczaj wskazanie break braku instrukcji.If this error occurs, it is typically an indication that a break statement is missing.
  • Jest to błąd czasu kompilacji dla punktu końcowego bloku elementu członkowskiego funkcji, który oblicza wartość jako osiągalną.It is a compile-time error for the end point of the block of a function member that computes a value to be reachable. W przypadku wystąpienia tego błędu zwykle jest to wskazanie, że return brakuje instrukcji.If this error occurs, it typically is an indication that a return statement is missing.

BlokiBlocks

Blok umożliwia zapisanie wielu instrukcji w kontekstach, w których Pojedyncza instrukcja jest dozwolona.A block permits multiple statements to be written in contexts where a single statement is allowed.

block
    : '{' statement_list? '}'
    ;

Blok składa się z opcjonalnych statement_list (list instrukcji) ujętych w nawiasy klamrowe.A block consists of an optional statement_list (Statement lists), enclosed in braces. Jeśli lista instrukcji zostanie pominięta, blok jest określany jako pusty.If the statement list is omitted, the block is said to be empty.

Blok może zawierać instrukcje deklaracji (instrukcje deklaracji).A block may contain declaration statements (Declaration statements). Zakres zmiennej lokalnej lub stałej zadeklarowanej w bloku jest blokiem.The scope of a local variable or constant declared in a block is the block.

Blok jest wykonywany w następujący sposób:A block is executed as follows:

  • Jeśli blok jest pusty, sterowanie jest przekazywane do punktu końcowego bloku.If the block is empty, control is transferred to the end point of the block.
  • Jeśli blok nie jest pusty, sterowanie jest przekazywane do listy instrukcji.If the block is not empty, control is transferred to the statement list. Gdy i Jeśli kontrolka osiągnie punkt końcowy listy instrukcji, sterowanie jest przekazywane do punktu końcowego bloku.When and if control reaches the end point of the statement list, control is transferred to the end point of the block.

Lista instrukcji bloku jest osiągalna, jeśli blok jest osiągalny.The statement list of a block is reachable if the block itself is reachable.

Punkt końcowy bloku jest osiągalny, jeśli blok jest pusty lub jeśli punkt końcowy listy instrukcji jest osiągalny.The end point of a block is reachable if the block is empty or if the end point of the statement list is reachable.

Blok zawierający jedną lub więcej yield instrukcji (instrukcja Yield) nosi nazwę bloku iteratora.A block that contains one or more yield statements (The yield statement) is called an iterator block. Bloki iteratorów są używane do implementowania składowych funkcji jako Iteratory (Iteratory).Iterator blocks are used to implement function members as iterators (Iterators). Dodatkowe ograniczenia dotyczą bloków iteratora:Some additional restrictions apply to iterator blocks:

  • Jest to błąd czasu kompilacji dla return instrukcji, która ma być wyświetlana w bloku iteratora (ale yield return instrukcje są dozwolone).It is a compile-time error for a return statement to appear in an iterator block (but yield return statements are permitted).
  • Jest to błąd czasu kompilacji dla bloku iteratora, który zawiera niebezpieczny kontekst (niebezpieczne konteksty).It is a compile-time error for an iterator block to contain an unsafe context (Unsafe contexts). Blok iteratora zawsze definiuje bezpieczny kontekst, nawet jeśli jego deklaracja jest zagnieżdżona w niebezpiecznym kontekście.An iterator block always defines a safe context, even when its declaration is nested in an unsafe context.

Listy instrukcjiStatement lists

Lista instrukcji* _ składa się z co najmniej jednej instrukcji, która jest zapisywana w sekwencji.A *statement list _ consists of one or more statements written in sequence. Listy instrukcji występują w _block * s (bloki) i w switch_block s (instrukcja SWITCH).Statement lists occur in _block*s (Blocks) and in switch_block s (The switch statement).

statement_list
    : statement+
    ;

Lista instrukcji jest wykonywana przez przeniesienie kontroli do pierwszej instrukcji.A statement list is executed by transferring control to the first statement. Gdy i Jeśli kontrolka osiągnie punkt końcowy instrukcji, sterowanie jest przekazywane do następnej instrukcji.When and if control reaches the end point of a statement, control is transferred to the next statement. Gdy i Jeśli kontrolka osiągnie punkt końcowy ostatniej instrukcji, sterowanie jest przekazywane do punktu końcowego listy instrukcji.When and if control reaches the end point of the last statement, control is transferred to the end point of the statement list.

Instrukcja na liście instrukcji jest dostępna, jeśli co najmniej jeden z następujących warunków jest spełniony:A statement in a statement list is reachable if at least one of the following is true:

  • Instrukcja jest pierwszą instrukcją i sama lista instrukcji jest osiągalna.The statement is the first statement and the statement list itself is reachable.
  • Punkt końcowy poprzedniej instrukcji jest osiągalny.The end point of the preceding statement is reachable.
  • Instrukcja jest instrukcją z etykietą, a etykieta jest przywoływana przez instrukcję osiągalną goto .The statement is a labeled statement and the label is referenced by a reachable goto statement.

Punkt końcowy listy instrukcji jest dostępny, jeśli punkt końcowy ostatniej instrukcji na liście jest osiągalny.The end point of a statement list is reachable if the end point of the last statement in the list is reachable.

Pusta instrukcjaThe empty statement

Empty_statement nic nie robi.An empty_statement does nothing.

empty_statement
    : ';'
    ;

Pusta instrukcja jest używana, gdy nie ma żadnych operacji do wykonania w kontekście, w którym instrukcja jest wymagana.An empty statement is used when there are no operations to perform in a context where a statement is required.

Wykonanie pustej instrukcji po prostu przenosi kontrolę do punktu końcowego instrukcji.Execution of an empty statement simply transfers control to the end point of the statement. W związku z tym punkt końcowy pustej instrukcji jest osiągalny, jeśli pusta instrukcja jest osiągalna.Thus, the end point of an empty statement is reachable if the empty statement is reachable.

Pustą instrukcję można użyć podczas pisania while instrukcji z pustą treścią:An empty statement can be used when writing a while statement with a null body:

bool ProcessMessage() {...}

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

Ponadto można użyć pustej instrukcji, aby zadeklarować etykietę tuż przed zamykaniem " } " bloku: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: ;
}

Instrukcje oznaczoneLabeled statements

Labeled_statement umożliwia prefiks instrukcji poprzedzony przez etykietę.A labeled_statement permits a statement to be prefixed by a label. Instrukcje z etykietami są dozwolone w blokach, ale nie są dozwolone jako osadzone instrukcje.Labeled statements are permitted in blocks, but are not permitted as embedded statements.

labeled_statement
    : identifier ':' statement
    ;

Instrukcja labeled deklaruje etykietę o nazwie podaną przez Identyfikator.A labeled statement declares a label with the name given by the identifier. Zakres etykiety to cały blok, w którym jest zadeklarowana etykieta, w tym wszelkie zagnieżdżone bloki.The scope of a label is the whole block in which the label is declared, including any nested blocks. Jest to błąd czasu kompilacji dla dwóch etykiet o tej samej nazwie, aby mieć nakładające się zakresy.It is a compile-time error for two labels with the same name to have overlapping scopes.

Do etykiet można odwoływać się z goto instrukcji (instrukcji goto) w zakresie etykiety.A label can be referenced from goto statements (The goto statement) within the scope of the label. Oznacza to, że goto instrukcje mogą przekazywać kontrolę w blokach i poza bloki, ale nigdy nie w blokach.This means that goto statements can transfer control within blocks and out of blocks, but never into blocks.

Etykiety mają własne miejsce deklaracji i nie zakłócają innych identyfikatorów.Labels have their own declaration space and do not interfere with other identifiers. PrzykładThe example

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

jest prawidłowy i używa nazwy x zarówno jako parametru, jak i etykiety.is valid and uses the name x as both a parameter and a label.

Wykonanie instrukcji oznaczonej etykietą odpowiada dokładnie na wykonanie instrukcji następującej po etykiecie.Execution of a labeled statement corresponds exactly to execution of the statement following the label.

Oprócz osiągalności zapewnianej przez normalny przepływ sterowania, instrukcja z etykietą jest osiągalna, jeśli do etykiety odwołuje się osiągalna goto instrukcja.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. (Wyjątek: Jeśli goto instrukcja znajduje się wewnątrz elementu, try który zawiera finally blok, a instrukcja z etykietą jest poza try , a punkt końcowy finally bloku jest nieosiągalny, instrukcja z etykietą jest nieosiągalna z tej goto instrukcji).(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.)

Deklaracje deklaracjiDeclaration statements

Declaration_statement deklaruje lokalną zmienną lub stałą.A declaration_statement declares a local variable or constant. Instrukcje deklaracji są dozwolone w blokach, ale nie są dozwolone jako osadzone instrukcje.Declaration statements are permitted in blocks, but are not permitted as embedded statements.

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

Deklaracje zmiennej lokalnejLocal variable declarations

Local_variable_declaration deklaruje co najmniej jedną zmienną lokalną.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
    ;

Local_variable_type local_variable_declaration bezpośrednio określa typ zmiennych wprowadzonych przez deklarację lub wskazuje identyfikator var , który powinien zostać wywnioskowany na podstawie inicjatora.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. Po tym typie następuje lista local_variable_declarator s, z których każdy wprowadza nową zmienną.The type is followed by a list of local_variable_declarator s, each of which introduces a new variable. Local_variable_declarator składa się z identyfikatora , który nazywa zmienną, opcjonalnie po której następuje = token "" i local_variable_initializer , która daje początkową wartość zmiennej.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.

W kontekście deklaracji zmiennej lokalnej, identyfikator var działa jako kontekstowe słowo kluczowe (słowa kluczowe). Gdy local_variable_type jest określony jako var i nie ma żadnego typu o nazwach var w zakresie, deklaracja jest niejawnie wpisaną deklaracją zmiennej lokalnej, której typ jest wywnioskowany na podstawie typu skojarzonego wyrażenia inicjatora.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. Niejawnie wpisane deklaracje zmiennych lokalnych podlegają następującym ograniczeniom:Implicitly typed local variable declarations are subject to the following restrictions:

  • Local_variable_declaration nie może zawierać wielu local_variable_declarator s.The local_variable_declaration cannot include multiple local_variable_declarator s.
  • Local_variable_declarator musi zawierać local_variable_initializer.The local_variable_declarator must include a local_variable_initializer.
  • Local_variable_initializer musi być wyrażeniem.The local_variable_initializer must be an expression.
  • Wyrażenie inicjatora musi mieć typ czasu kompilacji.The initializer expression must have a compile-time type.
  • Wyrażenie inicjatora nie może odwoływać się do zadeklarowanej zmiennejThe initializer expression cannot refer to the declared variable itself

Poniżej przedstawiono przykłady nieprawidłowych niejawnie wpisanych deklaracji zmiennych lokalnych: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

Wartość zmiennej lokalnej jest uzyskiwana w wyrażeniu przy użyciu simple_name (nazw prostych), a wartość zmiennej lokalnej jest modyfikowana przy użyciu przypisania (Operatory przypisania).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). Zmienna lokalna musi być ostatecznie przypisana (przypisanie określone) w każdej lokalizacji, w której jest uzyskiwana wartość.A local variable must be definitely assigned (Definite assignment) at each location where its value is obtained.

Zakres zmiennej lokalnej zadeklarowanej w local_variable_declaration to blok, w którym występuje deklaracja.The scope of a local variable declared in a local_variable_declaration is the block in which the declaration occurs. Jest to błąd, aby odwołać się do zmiennej lokalnej w pozycji tekstowej, która poprzedza local_variable_declarator zmiennej lokalnej.It is an error to refer to a local variable in a textual position that precedes the local_variable_declarator of the local variable. W zakresie zmiennej lokalnej jest to błąd czasu kompilacji, aby zadeklarować inną zmienną lokalną lub stałą o tej samej nazwie.Within the scope of a local variable, it is a compile-time error to declare another local variable or constant with the same name.

Deklaracja zmiennej lokalnej, która deklaruje wiele zmiennych, jest równoważna z wieloma deklaracjami pojedynczych zmiennych tego samego typu.A local variable declaration that declares multiple variables is equivalent to multiple declarations of single variables with the same type. Ponadto inicjator zmiennej w deklaracji zmiennej lokalnej odpowiada dokładnie instrukcji przypisania, która jest wstawiana bezpośrednio po deklaracji.Furthermore, a variable initializer in a local variable declaration corresponds exactly to an assignment statement that is inserted immediately after the declaration.

PrzykładThe example

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

odpowiada dokładnie nacorresponds exactly to

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

W deklaracji niejawnie wpisanej zmiennej lokalnej typ zadeklarowanej zmiennej lokalnej jest taki sam jak typ wyrażenia użytego do zainicjowania zmiennej.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. Na przykład: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>();

Niejawnie wpisane deklaracje zmiennej lokalnej są dokładnie równoważne z następującymi jawnie określonymi deklaracjami: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>();

Lokalne deklaracje stałychLocal constant declarations

Local_constant_declaration deklaruje co najmniej jedną stałą lokalną.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
    ;

Typ local_constant_declaration określa typ stałych wprowadzonych przez deklarację.The type of a local_constant_declaration specifies the type of the constants introduced by the declaration. Po tym typie następuje lista constant_declarator s, z których każdy wprowadza nową stałą.The type is followed by a list of constant_declarator s, each of which introduces a new constant. Constant_declarator składa się z identyfikatora , który nazywa stałą, po którym następuje = token "", po którym następuje constant_expression (wyrażenia stałe), która daje wartość stałej.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.

Typ i constant_expression deklaracji stałej lokalnej muszą być zgodne z tymi samymi regułami, co w deklaracji stałego elementu członkowskiego (stałe).The type and constant_expression of a local constant declaration must follow the same rules as those of a constant member declaration (Constants).

Wartość stałej lokalnej jest uzyskiwana w wyrażeniu przy użyciu simple_name (nazwy proste).The value of a local constant is obtained in an expression using a simple_name (Simple names).

Zakres stałej lokalnej to blok, w którym występuje deklaracja.The scope of a local constant is the block in which the declaration occurs. Jest to błąd, aby odwołać się do lokalnej stałej w pozycji tekstowej, która poprzedza jej constant_declarator.It is an error to refer to a local constant in a textual position that precedes its constant_declarator. W zakresie stałej lokalnej jest to błąd czasu kompilacji, aby zadeklarować inną zmienną lokalną lub stałą o tej samej nazwie.Within the scope of a local constant, it is a compile-time error to declare another local variable or constant with the same name.

Lokalna deklaracja stałej, która deklaruje wiele stałych jest równoznaczna z wieloma deklaracjami pojedynczych stałych tego samego typu.A local constant declaration that declares multiple constants is equivalent to multiple declarations of single constants with the same type.

Instrukcje wyrażeńExpression statements

Expression_statement oblicza danego wyrażenia.An expression_statement evaluates a given expression. Wartość obliczona przez wyrażenie (jeśli istnieje) jest odrzucana.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
    ;

Nie wszystkie wyrażenia są dozwolone jako instrukcje.Not all expressions are permitted as statements. W szczególności wyrażenia takie jak x + y i x == 1 , które tylko obliczają wartość (która zostanie odrzucona), nie są dozwolone jako instrukcje.In particular, expressions such as x + y and x == 1 that merely compute a value (which will be discarded), are not permitted as statements.

Wykonanie expression_statement oblicza wyrażenie zawarte, a następnie przekazuje kontrolę do punktu końcowego expression_statement.Execution of an expression_statement evaluates the contained expression and then transfers control to the end point of the expression_statement. Punkt końcowy expression_statement jest dostępny, jeśli expression_statement jest osiągalny.The end point of an expression_statement is reachable if that expression_statement is reachable.

Instrukcje wyboruSelection statements

Instrukcje wyboru wybierz jedną z wielu możliwych instrukcji do wykonania na podstawie wartości niektórych wyrażeń.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
    ;

Instrukcja ifThe if statement

ifInstrukcja wybiera instrukcję do wykonania na podstawie wartości wyrażenia logicznego.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
    ;

elseCzęść jest skojarzona z leksykalną najbliższą poprzednią if , która jest dozwolona przez składnię.An else part is associated with the lexically nearest preceding if that is allowed by the syntax. W tym celu, if instrukcja formularzaThus, an if statement of the form

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

jest równoważnyis equivalent to

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

ifInstrukcja jest wykonywana w następujący sposób:An if statement is executed as follows:

  • Boolean_expression (wyrażenia logiczne) są oceniane.The boolean_expression (Boolean expressions) is evaluated.
  • Jeśli wyrażenie logiczne daje true , sterowanie jest przekazywane do pierwszej osadzonej instrukcji.If the boolean expression yields true, control is transferred to the first embedded statement. Gdy i jeśli kontrola osiągnie punkt końcowy tej instrukcji, sterowanie jest przekazywane do punktu końcowego if instrukcji.When and if control reaches the end point of that statement, control is transferred to the end point of the if statement.
  • Jeśli wyrażenie logiczne zwraca wartość false i jeśli else część jest obecna, kontrola jest przekazywana do drugiej osadzonej instrukcji.If the boolean expression yields false and if an else part is present, control is transferred to the second embedded statement. Gdy i jeśli kontrola osiągnie punkt końcowy tej instrukcji, sterowanie jest przekazywane do punktu końcowego if instrukcji.When and if control reaches the end point of that statement, control is transferred to the end point of the if statement.
  • Jeśli wyrażenie logiczne zwraca wartość false i jeśli else część nie istnieje, kontrola jest przekazywana do punktu końcowego if instrukcji.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.

Pierwsza osadzona instrukcja if instrukcji jest osiągalna, jeśli if instrukcja jest osiągalna, a wyrażenie logiczne nie ma stałej wartości false .The first embedded statement of an if statement is reachable if the if statement is reachable and the boolean expression does not have the constant value false.

Druga osadzona instrukcja if instrukcji, jeśli jest obecna, jest osiągalna, jeśli if instrukcja jest osiągalna, a wyrażenie logiczne nie ma stałej wartości true .The second embedded statement of an if statement, if present, is reachable if the if statement is reachable and the boolean expression does not have the constant value true.

Punkt końcowy if instrukcji jest osiągalny, jeśli punkt końcowy co najmniej jednej z jej osadzonych instrukcji jest osiągalny.The end point of an if statement is reachable if the end point of at least one of its embedded statements is reachable. Ponadto punkt końcowy if instrukcji bez else części jest osiągalny, jeśli if instrukcja jest osiągalna, a wyrażenie logiczne nie ma stałej wartości true .In addition, the end point of an if statement with no else part is reachable if the if statement is reachable and the boolean expression does not have the constant value true.

Instrukcja SwitchThe switch statement

Instrukcja Switch wybiera do wykonania list instrukcji z skojarzoną etykietą Switch, która odpowiada wartości wyrażenia Switch.The switch statement selects for execution a statement list having an associated switch label that corresponds to the value of the switch expression.

switch_statement
    : 'switch' '(' expression ')' switch_block
    ;

switch_block
    : '{' switch_section* '}'
    ;

switch_section
    : switch_label+ statement_list
    ;

switch_label
    : 'case' constant_expression ':'
    | 'default' ':'
    ;

Switch_statement składa się ze słowa kluczowego switch , po którym następuje wyrażenie ujęte w nawiasy (zwane wyrażeniem Switch), po którym następuje switch_block.A switch_statement consists of the keyword switch, followed by a parenthesized expression (called the switch expression), followed by a switch_block. Switch_block składa się z zera lub więcej switch_section s ujętych w nawiasy klamrowe.The switch_block consists of zero or more switch_section s, enclosed in braces. Każda switch_section składa się z co najmniej jednego switch_label s, po którym następuje statement_list (Lista instrukcji).Each switch_section consists of one or more switch_label s followed by a statement_list (Statement lists).

Typ rządzący switch instrukcji jest ustalany przez wyrażenie Switch.The governing type of a switch statement is established by the switch expression.

  • Jeśli typ wyrażenia Switch to,,,,,,,,,, sbyte byte short ushort int uint long ulong bool char string lub enum_type, lub jeśli jest typem dopuszczającym wartość null odpowiadającym jednemu z tych typów, to jest to typ regulujący switch instrukcji.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.
  • W przeciwnym razie dokładnie jedna zdefiniowana przez użytkownika konwersja niejawna (konwersje zdefiniowane przez użytkownika) musi istnieć z typu wyrażenia przełącznika do jednego z następujących możliwych typów:,,,,,,,,, sbyte byte short ushort int uint long ulong char string lub, typu dopuszczającego wartość null odpowiadającego jednemu z tych typów.Otherwise, exactly one user-defined implicit conversion (User-defined conversions) must exist from the type of the switch expression to one of the following possible governing types: sbyte, byte, short, ushort, int, uint, long, ulong, char, string, or, a nullable type corresponding to one of those types.
  • W przeciwnym razie, jeśli taka niejawna konwersja nie istnieje lub jeśli istnieje więcej niż jedna taka niejawna konwersja, wystąpi błąd w czasie kompilacji.Otherwise, if no such implicit conversion exists, or if more than one such implicit conversion exists, a compile-time error occurs.

Wyrażenie stałe każdej case etykiety musi oznaczać wartość, która jest niejawnie przekonwertowana (konwersje niejawne) na typ decydujący switch instrukcji.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. Błąd czasu kompilacji występuje, jeśli co najmniej dwie case etykiety w tej samej switch instrukcji określają tę samą wartość stałą.A compile-time error occurs if two or more case labels in the same switch statement specify the same constant value.

W instrukcji switch może istnieć co najwyżej jedna default etykieta.There can be at most one default label in a switch statement.

switchInstrukcja jest wykonywana w następujący sposób:A switch statement is executed as follows:

  • Wyrażenie Switch jest oceniane i konwertowane na typ zarządzający.The switch expression is evaluated and converted to the governing type.
  • Jeśli jedna ze stałych określonych w case etykiecie w tej samej switch instrukcji jest równa wartości wyrażenia Switch, formant zostanie przeniesiony do listy instrukcji po dopasowanym case oznaczeniu.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.
  • Jeśli żadna ze stałych określonych w case etykietach w tej samej switch instrukcji nie jest równa wartości wyrażenia Switch i jeśli default etykieta jest obecna, sterowanie jest przekazywane do listy instrukcji po default etykiecie.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.
  • Jeśli żadna ze stałych określonych w case etykietach w tej samej switch instrukcji nie jest równa wartości wyrażenia Switch i jeśli żadna default etykieta nie jest obecna, kontrola jest przekazywana do punktu końcowego switch instrukcji.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.

Jeśli punkt końcowy listy instrukcji przełącznika jest osiągalny, wystąpi błąd w czasie kompilacji.If the end point of the statement list of a switch section is reachable, a compile-time error occurs. Ta wartość jest znana jako reguła "bez powracania".This is known as the "no fall through" rule. PrzykładThe example

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

jest prawidłowy, ponieważ żadna sekcja Switch nie ma osiągalnego punktu końcowego.is valid because no switch section has a reachable end point. W przeciwieństwie do języka C i C++, wykonanie sekcji Switch nie jest dozwolone w przypadku przechodzenia do kolejnej sekcji Switch i przykładuUnlike 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();
}

powoduje błąd czasu kompilacji.results in a compile-time error. Po wykonaniu sekcji Switch po wykonaniu kolejnej sekcji Switch goto case goto default musi być użyta jawna instrukcja or: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;
}

W switch_section jest dozwolonych wiele etykiet.Multiple labels are permitted in a switch_section. PrzykładThe example

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

jest prawidłowy.is valid. Przykład nie narusza reguły "No-through", ponieważ etykiety case 2: i default: są częścią tego samego switch_section.The example does not violate the "no fall through" rule because the labels case 2: and default: are part of the same switch_section.

Reguła "bez powracania" uniemożliwia wspólną klasę błędów występujących w C i C++, gdy break instrukcje są przypadkowo pomijane.The "no fall through" rule prevents a common class of bugs that occur in C and C++ when break statements are accidentally omitted. Ponadto ze względu na tę regułę sekcje przełącznika switch instrukcji można arbitralnie zmienić bez wpływu na zachowanie instrukcji.In addition, because of this rule, the switch sections of a switch statement can be arbitrarily rearranged without affecting the behavior of the statement. Na przykład sekcje switch powyższej instrukcji można odwrócić bez wpływu na zachowanie instrukcji: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;
}

Lista instrukcji switch zwykle kończy się w break goto case instrukcji,, lub goto default , ale dowolna konstrukcja, która renderuje punkt końcowy listy instrukcji jest nieosiągalna.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. Na przykład, while instrukcja kontrolowana przez wyrażenie logiczne true jest znana, aby nie dotrzeć do punktu końcowego.For example, a while statement controlled by the boolean expression true is known to never reach its end point. Podobnie, throw instrukcja lub return zawsze przenosi formant w innym miejscu i nigdy nie dociera do punktu końcowego.Likewise, a throw or return statement always transfers control elsewhere and never reaches its end point. W tym przypadku następujący przykład jest prawidłowy:Thus, the following example is valid:

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

Typ decydujący switch instrukcji może być typem string .The governing type of a switch statement may be the type string. Na przykład: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;
    }
}

Podobnie jak w przypadku operatorów równości ciągów (Operatory równości ciągów), switch instrukcja uwzględnia wielkość liter i wykona daną sekcję Switch tylko wtedy, gdy ciąg wyrażenia przełącznika dokładnie pasuje do case stałej etykiet.Like the string equality operators (String equality operators), the switch statement is case sensitive and will execute a given switch section only if the switch expression string exactly matches a case label constant.

W przypadku, gdy typem switch instrukcji jest string , wartość null jest dozwolona jako stała etykiet wielkości liter.When the governing type of a switch statement is string, the value null is permitted as a case label constant.

Statement_list s switch_block mogą zawierać instrukcje deklaracji (instrukcje deklaracji).The statement_list s of a switch_block may contain declaration statements (Declaration statements). Zakres zmiennej lokalnej lub stałej zadeklarowanej w bloku przełącznika to blok przełącznika.The scope of a local variable or constant declared in a switch block is the switch block.

Lista instrukcji danej sekcji Switch jest osiągalna, jeśli switch instrukcja jest osiągalna i co najmniej jeden z następujących warunków jest spełniony: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:

  • Wyrażenie Switch jest wartością niestałą.The switch expression is a non-constant value.
  • Wyrażenie Switch jest stałą wartością zgodną z case etykietą w sekcji Switch.The switch expression is a constant value that matches a case label in the switch section.
  • Wyrażenie Switch jest wartością stałą, która nie jest zgodna z żadną case etykietą, a sekcja Switch zawiera default etykietę.The switch expression is a constant value that doesn't match any case label, and the switch section contains the default label.
  • Do etykiety przełącznika w sekcji przełącznika jest przywoływana osiągalna goto case goto default instrukcja or.A switch label of the switch section is referenced by a reachable goto case or goto default statement.

Punkt końcowy switch instrukcji jest dostępny, jeśli co najmniej jeden z następujących warunków jest spełniony:The end point of a switch statement is reachable if at least one of the following is true:

  • switchInstrukcja zawiera osiągalną break instrukcję, która kończy switch wykonywanie instrukcji.The switch statement contains a reachable break statement that exits the switch statement.
  • switchInstrukcja jest osiągalna, wyrażenie Switch jest wartością niestałą i żadna default etykieta nie jest obecna.The switch statement is reachable, the switch expression is a non-constant value, and no default label is present.
  • switchInstrukcja jest osiągalna, wyrażenie Switch jest wartością stałą, która nie jest zgodna z żadną case etykietą i żadna default etykieta nie jest obecna.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.

Instrukcje iteracjiIteration statements

Instrukcja iteracji wielokrotnie wykonuje osadzoną instrukcję.Iteration statements repeatedly execute an embedded statement.

iteration_statement
    : while_statement
    | do_statement
    | for_statement
    | foreach_statement
    ;

Instrukcja whileThe while statement

whileInstrukcja warunkowo wykonuje osadzoną instrukcję zero lub więcej razy.The while statement conditionally executes an embedded statement zero or more times.

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

whileInstrukcja jest wykonywana w następujący sposób:A while statement is executed as follows:

  • Boolean_expression (wyrażenia logiczne) są oceniane.The boolean_expression (Boolean expressions) is evaluated.
  • Jeśli wyrażenie logiczne daje true , sterowanie jest przekazywane do osadzonej instrukcji.If the boolean expression yields true, control is transferred to the embedded statement. Gdy i Jeśli kontrolka osiągnie punkt końcowy osadzonej instrukcji (prawdopodobnie z wykonania continue instrukcji), sterowanie jest przekazywane na początek while instrukcji.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.
  • Jeśli wyrażenie logiczne daje false , sterowanie jest przekazywane do punktu końcowego while instrukcji.If the boolean expression yields false, control is transferred to the end point of the while statement.

Wewnątrz instrukcji osadzonej instrukcji instrukcja while break (instrukcja break) może być używana do transferowania kontroli do punktu końcowego while instrukcji (w związku z tym kończącej iterację osadzonej instrukcji), a continue instrukcja (Instrukcja continue) może być użyta do przetransferowania kontroli do punktu końcowego osadzonej instrukcji (w związku z tym wykonywanie innej iteracji while instrukcji).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).

Osadzona instrukcja while instrukcji jest osiągalna, jeśli while instrukcja jest osiągalna, a wyrażenie logiczne nie ma stałej wartości false .The embedded statement of a while statement is reachable if the while statement is reachable and the boolean expression does not have the constant value false.

Punkt końcowy while instrukcji jest dostępny, jeśli co najmniej jeden z następujących warunków jest spełniony:The end point of a while statement is reachable if at least one of the following is true:

  • whileInstrukcja zawiera osiągalną break instrukcję, która kończy while wykonywanie instrukcji.The while statement contains a reachable break statement that exits the while statement.
  • whileInstrukcja jest osiągalna, a wyrażenie logiczne nie ma stałej wartości true .The while statement is reachable and the boolean expression does not have the constant value true.

Instrukcja doThe do statement

doInstrukcja warunkowo wykonuje osadzoną instrukcję jeden lub więcej razy.The do statement conditionally executes an embedded statement one or more times.

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

doInstrukcja jest wykonywana w następujący sposób:A do statement is executed as follows:

  • Kontrolka jest przenoszona do osadzonej instrukcji.Control is transferred to the embedded statement.
  • Gdy i Jeśli kontrolka osiągnie punkt końcowy osadzonej instrukcji (prawdopodobnie z wykonania continue instrukcji), jest obliczana Boolean_expression (wyrażenia logiczne).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. Jeśli wyrażenie logiczne daje true , sterowanie jest przekazywane na początek do instrukcji.If the boolean expression yields true, control is transferred to the beginning of the do statement. W przeciwnym razie kontrola jest przekazywana do punktu końcowego do instrukcji.Otherwise, control is transferred to the end point of the do statement.

W osadzonym zestawie instrukcji instrukcja do break (instrukcja break) może być używana do transferowania kontroli do punktu końcowego do instrukcji (w związku z tym kończącej iterację osadzonej instrukcji), a continue instrukcja (Instrukcja continue) może być używana do transferowania kontroli do punktu końcowego osadzonej instrukcji.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.

Osadzona instrukcja do instrukcji jest osiągalna, jeśli do instrukcja jest osiągalna.The embedded statement of a do statement is reachable if the do statement is reachable.

Punkt końcowy do instrukcji jest dostępny, jeśli co najmniej jeden z następujących warunków jest spełniony:The end point of a do statement is reachable if at least one of the following is true:

  • doInstrukcja zawiera osiągalną break instrukcję, która kończy do wykonywanie instrukcji.The do statement contains a reachable break statement that exits the do statement.
  • Punkt końcowy osadzonej instrukcji jest osiągalny, a wyrażenie logiczne nie ma stałej wartości true .The end point of the embedded statement is reachable and the boolean expression does not have the constant value true.

Instrukcja forThe for statement

forInstrukcja oblicza sekwencję wyrażeń inicjalizacji, a następnie, gdy warunek ma wartość true, wielokrotnie wykonuje osadzoną instrukcję i szacuje sekwencję wyrażeń iteracji.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, jeśli jest obecny, składa się z local_variable_declaration (lokalnych deklaracji zmiennych) lub listy statement_expression s (instrukcje wyrażeń) oddzielonych przecinkami.The for_initializer, if present, consists of either a local_variable_declaration (Local variable declarations) or a list of statement_expression s (Expression statements) separated by commas. Zakres zmiennej lokalnej zadeklarowanej przez for_initializer zaczyna się od local_variable_declarator dla zmiennej i rozciąga się na koniec osadzonej instrukcji.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. Zakres zawiera for_condition i for_iterator.The scope includes the for_condition and the for_iterator.

For_condition, jeśli jest obecny, musi być Boolean_expression (wyrażenia logiczne).The for_condition, if present, must be a boolean_expression (Boolean expressions).

For_iterator, jeśli jest obecny, składa się z listy statement_expression s (instrukcje wyrażeń) oddzielonych przecinkami.The for_iterator, if present, consists of a list of statement_expression s (Expression statements) separated by commas.

Instrukcja for jest wykonywana w następujący sposób:A for statement is executed as follows:

  • Jeśli istnieje for_initializer , inicjatory zmiennych lub wyrażenia instrukcji są wykonywane w kolejności, w jakiej zostały wpisane.If a for_initializer is present, the variable initializers or statement expressions are executed in the order they are written. Ten krok jest wykonywany tylko raz.This step is only performed once.
  • Jeśli istnieje for_condition , zostanie ona oceniona.If a for_condition is present, it is evaluated.
  • Jeśli for_condition nie istnieje lub w przypadku oceny true , kontrola jest przekazywana do osadzonej instrukcji.If the for_condition is not present or if the evaluation yields true, control is transferred to the embedded statement. Gdy i jeśli kontrola osiągnie punkt końcowy osadzonej instrukcji (prawdopodobnie z wykonania continue instrukcji), wyrażenia for_iterator, jeśli istnieją, są oceniane w sekwencji, a następnie wykonywana jest inna iteracja, rozpoczynając od oceny for_condition w powyższym kroku.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.
  • Jeśli for_condition jest obecny i oceny ocen false , kontrola jest przekazywana do punktu końcowego for instrukcji.If the for_condition is present and the evaluation yields false, control is transferred to the end point of the for statement.

W osadzonej instrukcji for instrukcji, break instrukcja (instrukcja break) może być używana do transferowania kontroli do punktu końcowego for instrukcji (w związku z tym kończącej iterację osadzonej instrukcji) i continue instrukcji (Instrukcja continue) może służyć do transferowania kontroli do punktu końcowego osadzonej instrukcji (w związku z tym wykonywanie for_iterator i wykonywanie innej iteracji for instrukcji, rozpoczynając od 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).

Osadzona instrukcja for instrukcji jest osiągalna, jeśli jedno z następujących warunków jest prawdziwe:The embedded statement of a for statement is reachable if one of the following is true:

  • forInstrukcja jest osiągalna i nie ma for_condition .The for statement is reachable and no for_condition is present.
  • forInstrukcja jest osiągalna, a for_condition istnieje i nie ma stałej wartości false .The for statement is reachable and a for_condition is present and does not have the constant value false.

Punkt końcowy for instrukcji jest dostępny, jeśli co najmniej jeden z następujących warunków jest spełniony:The end point of a for statement is reachable if at least one of the following is true:

  • forInstrukcja zawiera osiągalną break instrukcję, która kończy for wykonywanie instrukcji.The for statement contains a reachable break statement that exits the for statement.
  • forInstrukcja jest osiągalna, a for_condition istnieje i nie ma stałej wartości true .The for statement is reachable and a for_condition is present and does not have the constant value true.

Instrukcja foreachThe foreach statement

foreachInstrukcja wylicza elementy kolekcji, wykonując osadzoną instrukcję dla każdego elementu kolekcji.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
    ;

Typ i Identyfikator foreach instrukcji deklaruje *Zmienna iteracji _ instrukcji.The type and identifier of a foreach statement declare the *iteration variable _ of the statement. Jeśli var Identyfikator jest podany jako _local_variable_type *, a typ o nazwie nie należy var do zakresu, Zmienna iteracji jest określana jako Zmienna iteracji niejawnie wpisanej, a jej typ jest traktowany jako typ elementu foreach instrukcji, jak określono poniżej.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. Zmienna iteracji odnosi się do zmiennej lokalnej tylko do odczytu z zakresem, który wykracza poza osadzoną instrukcję.The iteration variable corresponds to a read-only local variable with a scope that extends over the embedded statement. Podczas wykonywania foreach instrukcji Zmienna iteracji reprezentuje element kolekcji, dla którego obecnie trwa wykonywanie iteracji.During execution of a foreach statement, the iteration variable represents the collection element for which an iteration is currently being performed. Błąd czasu kompilacji występuje, jeśli osadzona instrukcja próbuje zmodyfikować zmienną iteracji (poprzez przypisanie lub ++ -- Operatory i) albo przekazać zmienną iteracji jako ref out parametr lub.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.

W następujących przypadkach dla zwięzłości, IEnumerable , IEnumerator IEnumerable<T> i zapoznaj się z IEnumerator<T> odpowiednimi typami w przestrzeniach nazw System.Collections i System.Collections.Generic .In the following, for brevity, IEnumerable, IEnumerator, IEnumerable<T> and IEnumerator<T> refer to the corresponding types in the namespaces System.Collections and System.Collections.Generic.

Przetwarzanie w czasie kompilacji instrukcji foreach najpierw określa Typ kolekcji* , Typ modułu wyliczającego i _ Typ elementu* wyrażenia.The compile-time processing of a foreach statement first determines the collection type _, _enumerator type* and _ element type* of the expression. To obliczanie jest przeprowadzane w następujący sposób:This determination proceeds as follows:

  • Jeśli typ X wyrażenia jest typem tablicy, istnieje niejawna konwersja odwołania z X do IEnumerable interfejsu (ponieważ System.Array implementuje ten interfejs).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). Typ kolekcji _ jest IEnumerable interfejsem, _typem modułu wyliczającego*_ jest IEnumerator interfejs, a Typ elementu _ * jest typem elementu typu tablicy X .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.

  • Jeśli typem X wyrażenia jest dynamic , istnieje niejawna konwersja z wyrażenia do IEnumerable interfejsu (niejawne konwersje dynamiczne).If the type X of expression is dynamic then there is an implicit conversion from expression to the IEnumerable interface (Implicit dynamic conversions). Typ kolekcji _ jest IEnumerable interfejsem, a _typem modułu wyliczającego*_ jest IEnumerator interfejs.The collection type _ is the IEnumerable interface and the _enumerator type*_ is the IEnumerator interface. Jeśli var Identyfikator jest określony jako _local_variable_type *, wówczas typem elementu jest dynamic , w przeciwnym razie object .If the var identifier is given as the _local_variable_type* then the element type is dynamic, otherwise it is object.

  • W przeciwnym razie Ustal, czy typ X ma odpowiednią GetEnumerator metodę:Otherwise, determine whether the type X has an appropriate GetEnumerator method:

    • Wykonaj wyszukiwanie elementów członkowskich w typie X z identyfikatorem GetEnumerator i bez argumentów typu.Perform member lookup on the type X with identifier GetEnumerator and no type arguments. Jeśli wyszukiwanie elementu członkowskiego nie produkuje dopasowania lub tworzy niejednoznaczność lub tworzy dopasowanie, które nie jest grupą metod, należy sprawdzić, czy wyliczalny interfejs został opisany poniżej.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. Zaleca się, aby ostrzeżenie było wydawane, gdy wyszukiwanie elementów członkowskich produkuje wszystkie elementy poza grupą metod lub nie odpowiada.It is recommended that a warning be issued if member lookup produces anything except a method group or no match.
    • Wykonaj rozwiązanie przeciążenia przy użyciu grupy metod i pustej listy argumentów.Perform overload resolution using the resulting method group and an empty argument list. Jeśli rozwiązanie przeciążenia skutkuje brakiem odpowiednich metod, wyniki są niejednoznaczne lub mają jedną najlepszą metodę, ale ta metoda jest statyczna lub nie jest publiczna, Wyszukaj wyliczalny interfejs zgodnie z poniższym opisem.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. Zaleca się, aby ostrzeżenie było wydawane, jeśli rozwiązanie przeciążania produkuje wszystko, z wyjątkiem jednoznacznej metody wystąpienia publicznego lub nie ma zastosowania do odpowiednich metod.It is recommended that a warning be issued if overload resolution produces anything except an unambiguous public instance method or no applicable methods.
    • Jeśli zwracany typ E GetEnumerator metody nie jest klasą, strukturą lub typem interfejsu, jest generowany błąd i nie są podejmowane żadne dalsze kroki.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.
    • Wyszukiwanie elementu członkowskiego jest wykonywane na E z identyfikatorem Current i bez argumentów typu.Member lookup is performed on E with the identifier Current and no type arguments. Jeśli wyszukiwanie elementu członkowskiego nie powoduje dopasowania, wynikiem jest błąd lub wynikiem jest wszystko z wyjątkiem właściwości wystąpienia publicznego, która umożliwia odczytywanie, zostanie wygenerowany błąd i nie są podejmowane żadne dalsze kroki.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.
    • Wyszukiwanie elementu członkowskiego jest wykonywane na E z identyfikatorem MoveNext i bez argumentów typu.Member lookup is performed on E with the identifier MoveNext and no type arguments. Jeśli wyszukiwanie elementu członkowskiego nie powoduje dopasowania, wynikiem jest błąd lub wynikiem jest wszystko poza grupą metod, zostanie wygenerowany błąd i nie są podejmowane żadne dalsze kroki.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.
    • Rozpoznanie przeciążenia jest wykonywane w grupie metod z pustą listą argumentów.Overload resolution is performed on the method group with an empty argument list. Jeśli rozwiązanie przeciążenia skutkuje brakiem odpowiednich metod, wyniki są niejednoznaczne lub mają jedną najlepszą metodę, ale ta metoda jest statyczna lub nie jest publiczna lub jej typem zwracanym jest bool błąd i nie są podejmowane żadne dalsze kroki.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.
    • Typ kolekcji _ ma wartość X , _Typ wyliczającego_ to E , a _ element Type jest typem Current właściwości.The collection type _ is X, the _enumerator type_ is E, and the _ element type is the type of the Current property.
  • W przeciwnym razie Sprawdź, czy wyliczalny interfejs:Otherwise, check for an enumerable interface:

    • Jeśli wśród wszystkich typów Ti , dla których istnieje niejawna konwersja z X do IEnumerable<Ti> , istnieje unikatowy typ, T który T nie jest dynamic i dla wszystkich pozostałych Ti istnieje niejawna konwersja z IEnumerable<T> do na IEnumerable<Ti> , a następnie Typ kolekcji* _ jest interfejsem IEnumerable<T> , typem modułu wyliczającego jest interfejs IEnumerator<T> , a Typ elementu _ * ma wartość 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.
    • W przeciwnym razie, jeśli istnieje więcej niż jeden taki typ T , zostanie wygenerowany błąd i nie zostaną wykonane żadne dalsze kroki.Otherwise, if there is more than one such type T, then an error is produced and no further steps are taken.
    • W przeciwnym razie, jeśli istnieje niejawna konwersja z X do System.Collections.IEnumerable interfejsu, wówczas Typ kolekcji* _ jest tym interfejsem, typem modułu wyliczającego jest interfejs System.Collections.IEnumerator , a Typ elementu _ * ma wartość 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.
    • W przeciwnym razie zostanie wygenerowany błąd i nie są podejmowane żadne dalsze kroki.Otherwise, an error is produced and no further steps are taken.

Powyższe kroki, w przypadku powodzenia, jednoznacznie tworzą typ kolekcji C , typ modułu wyliczającego E i typ elementu T .The above steps, if successful, unambiguously produce a collection type C, enumerator type E and element type T. Instrukcja foreach formularzaA foreach statement of the form

foreach (V v in x) embedded_statement

następnie jest rozwinięty do:is then expanded to:

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

Zmienna e nie jest widoczna lub dostępna dla wyrażenia x lub osadzonej instrukcji ani żadnego innego kodu źródłowego programu.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. Zmienna v jest tylko do odczytu w osadzonej instrukcji.The variable v is read-only in the embedded statement. Jeśli nie istnieje jawna konwersja (jawne konwersje) z T (typ elementu) do V ( local_variable_type w instrukcji foreach), zostanie wygenerowany błąd i nie są podejmowane żadne dalsze kroki.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. Jeśli x ma wartość null , System.NullReferenceException jest zgłaszany w czasie wykonywania.If x has the value null, a System.NullReferenceException is thrown at run-time.

Implementacja może zaimplementować daną instrukcję foreach inaczej, np. ze względu na wydajność, o ile zachowanie jest spójne z powyższym rozszerzeniem.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.

Umieszczenie v wewnątrz pętli while jest ważne dla sposobu, w jaki są przechwytywane przez jakąkolwiek funkcję anonimową występującą w embedded_statement.The placement of v inside the while loop is important for how it is captured by any anonymous function occurring in the embedded_statement.

Na przykład: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();

Jeśli v został zadeklarowany poza pętlą while, będzie współużytkowana przez wszystkie iteracje, a jej wartość po pętli for będzie wartością końcową, czyli to 13 , co to jest wywołanie f .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. Zamiast tego, ponieważ każda iteracja ma własną zmienną v , przechwycona przez f w pierwszej iteracji będzie nadal przechowywać wartość, co 7 oznacza, że zostanie wydrukowany.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. (Uwaga: wcześniejsze wersje języka C# zadeklarowane v poza pętlą while).(Note: earlier versions of C# declared v outside of the while loop.)

Treść bloku finally jest tworzona zgodnie z poniższymi krokami:The body of the finally block is constructed according to the following steps:

  • Jeśli istnieje niejawna konwersja z E do System.IDisposable interfejsu,If there is an implicit conversion from E to the System.IDisposable interface, then

    • Jeśli E jest typem wartości niedopuszczających wartości null, klauzula finally jest rozwinięta do semantycznego odpowiednika:If E is a non-nullable value type then the finally clause is expanded to the semantic equivalent of:

      finally {
          ((System.IDisposable)e).Dispose();
      }
      
    • W przeciwnym razie klauzula finally jest rozwinięta do semantycznego odpowiednika:Otherwise the finally clause is expanded to the semantic equivalent of:

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

    z tą różnicą, że jeśli E jest typem wartości, lub parametrem typu skonkretyzowanym do typu wartości, Rzutowanie e na System.IDisposable nie spowoduje wystąpienia opakowania.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.

  • W przeciwnym razie, jeśli E jest typem zapieczętowanym, klauzula finally jest rozwinięta do pustego bloku:Otherwise, if E is a sealed type, the finally clause is expanded to an empty block:

    finally {
    }
    
  • W przeciwnym razie klauzula finally jest rozwinięta do:Otherwise, the finally clause is expanded to:

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

    Zmienna lokalna d nie jest widoczna dla żadnego kodu użytkownika ani nie jest dostępna dla żadnego z nich.The local variable d is not visible to or accessible to any user code. W szczególności nie powoduje konfliktu z żadną inną zmienną, której zakres zawiera blok finally.In particular, it does not conflict with any other variable whose scope includes the finally block.

Kolejność, w której foreach przechodzą elementy tablicy, jest następująca: w przypadku elementów tablic jednowymiarowych odbywa się rosnącą kolejnością indeksu, rozpoczynając od indeksu  0 i kończąc z indeksem Length - 1 .The order in which foreach traverses the elements of an array, is as follows: For single-dimensional arrays elements are traversed in increasing index order, starting with index 0 and ending with index Length - 1. W przypadku tablic wielowymiarowych elementy są przenoszone w taki sposób, że indeksy w wymiarze z prawej strony są najpierw zwiększane, następnie następny lewy wymiar itd.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.

Poniższy przykład drukuje każdą wartość w dwuwymiarowej tablicy, w kolejności elementów: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();
    }
}

Utworzone dane wyjściowe są następujące:The output produced is as follows:

1.2 2.3 3.4 4.5 5.6 6.7 7.8 8.9

W przykładzieIn the example

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

Typ n elementu jest wywnioskowany na wartość int numbersthe type of n is inferred to be int, the element type of numbers.

Instrukcje skokuJump statements

Instrukcje skoku bezwarunkowo przetransferować kontrolę.Jump statements unconditionally transfer control.

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

Lokalizacja, do której instrukcja skoku przeniesie formant jest nazywana elementem docelowym instrukcji skoku.The location to which a jump statement transfers control is called the target of the jump statement.

Gdy instrukcja skoku występuje w bloku, a obiekt docelowy tej instrukcji skoku znajduje się poza tym blokiem, instrukcja skoku jest określana w celu opuszczenia bloku.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. Chociaż instrukcja skoku może przetransferować kontrolę z bloku, nigdy nie można przesłać kontroli do bloku.While a jump statement may transfer control out of a block, it can never transfer control into a block.

Wykonywanie instrukcji skoku jest skomplikowane przez obecność instrukcji wykonywanych przez interwencję try .Execution of jump statements is complicated by the presence of intervening try statements. W przypadku braku takich try instrukcji instrukcja skoku bezwarunkowo przesyła kontrolę z instrukcji skoku do jej obiektu docelowego.In the absence of such try statements, a jump statement unconditionally transfers control from the jump statement to its target. W obecności takich try instrukcji, wykonywanie jest bardziej skomplikowane.In the presence of such intervening try statements, execution is more complex. Jeśli instrukcja skoku kończy jeden lub więcej try bloków ze skojarzonymi finally blokami, kontrola jest początkowo przekazywana do finally bloku wewnętrznej try instrukcji.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. Gdy i jeśli kontrola osiągnie punkt końcowy finally bloku, sterowanie jest przekazywane do finally bloku następnej otaczającej try instrukcji.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. Ten proces jest powtarzany do momentu finally wykonania bloków wszystkich try instrukcji interwencji.This process is repeated until the finally blocks of all intervening try statements have been executed.

W przykładzieIn 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");
    }
}

finallybloki skojarzone z dwiema try instrukcjami są wykonywane przed przekazaniem kontroli do elementu docelowego instrukcji skoku.the finally blocks associated with two try statements are executed before control is transferred to the target of the jump statement.

Utworzone dane wyjściowe są następujące:The output produced is as follows:

Before break
Innermost finally block
Outermost finally block
After break

Instrukcja breakThe break statement

breakInstrukcja kończy najbliższych otaczających switch ,,,, while do for lub foreach instrukcji.The break statement exits the nearest enclosing switch, while, do, for, or foreach statement.

break_statement
    : 'break' ';'
    ;

Obiekt docelowy break instrukcji jest punktem końcowym najbliższej otaczającej switch ,,,, while do for lub foreach instrukcji.The target of a break statement is the end point of the nearest enclosing switch, while, do, for, or foreach statement. Jeśli break instrukcja nie jest ujęta w switch instrukcji, while , do , for lub foreach , wystąpi błąd w czasie kompilacji.If a break statement is not enclosed by a switch, while, do, for, or foreach statement, a compile-time error occurs.

Gdy wiele switch while instrukcji,, do , for lub foreach są zagnieżdżone w obrębie siebie, break instrukcja ma zastosowanie tylko do najbardziej wewnętrznej instrukcji.When multiple switch, while, do, for, or foreach statements are nested within each other, a break statement applies only to the innermost statement. Aby przenieść kontrolę na wiele poziomów zagnieżdżenia, goto należy użyć instrukcji (instrukcji goto).To transfer control across multiple nesting levels, a goto statement (The goto statement) must be used.

breakInstrukcja nie może opuścić finally bloku (Instrukcja try).A break statement cannot exit a finally block (The try statement). Gdy break instrukcja występuje w finally bloku, obiekt docelowy break instrukcji musi znajdować się w tym samym finally bloku; w przeciwnym razie wystąpi błąd w czasie kompilacji.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.

breakInstrukcja jest wykonywana w następujący sposób:A break statement is executed as follows:

  • Jeśli break instrukcja kończy jeden lub więcej try bloków ze skojarzonymi finally blokami, kontrola jest początkowo przekazywana do finally bloku wewnętrznej try instrukcji.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. Gdy i jeśli kontrola osiągnie punkt końcowy finally bloku, sterowanie jest przekazywane do finally bloku następnej otaczającej try instrukcji.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. Ten proces jest powtarzany do momentu finally wykonania bloków wszystkich try instrukcji interwencji.This process is repeated until the finally blocks of all intervening try statements have been executed.
  • Kontrolka jest przenoszona do elementu docelowego break instrukcji.Control is transferred to the target of the break statement.

Ponieważ break instrukcja bezwarunkowo transferuje kontrolę w innym miejscu, punkt końcowy break instrukcji nie jest nigdy osiągalny.Because a break statement unconditionally transfers control elsewhere, the end point of a break statement is never reachable.

Instrukcja continueThe continue statement

continueInstrukcja uruchamia nową iterację najbliższej otaczającej while , do , for , lub foreach instrukcji.The continue statement starts a new iteration of the nearest enclosing while, do, for, or foreach statement.

continue_statement
    : 'continue' ';'
    ;

Obiekt docelowy continue instrukcji jest punktem końcowym osadzonej instrukcji najbliższej otaczającej while , do , for lub foreach instrukcji.The target of a continue statement is the end point of the embedded statement of the nearest enclosing while, do, for, or foreach statement. Jeśli continue instrukcja nie jest ujęta w while instrukcji, do , for , lub foreach , wystąpi błąd w czasie kompilacji.If a continue statement is not enclosed by a while, do, for, or foreach statement, a compile-time error occurs.

Gdy wiele while do instrukcji,, for , lub foreach są zagnieżdżone w obrębie siebie, continue instrukcja ma zastosowanie tylko do najbardziej wewnętrznej instrukcji.When multiple while, do, for, or foreach statements are nested within each other, a continue statement applies only to the innermost statement. Aby przenieść kontrolę na wiele poziomów zagnieżdżenia, goto należy użyć instrukcji (instrukcji goto).To transfer control across multiple nesting levels, a goto statement (The goto statement) must be used.

continueInstrukcja nie może opuścić finally bloku (Instrukcja try).A continue statement cannot exit a finally block (The try statement). Gdy continue instrukcja występuje w finally bloku, obiekt docelowy continue instrukcji musi znajdować się w tym samym finally bloku; w przeciwnym razie wystąpi błąd w czasie kompilacji.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.

continueInstrukcja jest wykonywana w następujący sposób:A continue statement is executed as follows:

  • Jeśli continue instrukcja kończy jeden lub więcej try bloków ze skojarzonymi finally blokami, kontrola jest początkowo przekazywana do finally bloku wewnętrznej try instrukcji.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. Gdy i jeśli kontrola osiągnie punkt końcowy finally bloku, sterowanie jest przekazywane do finally bloku następnej otaczającej try instrukcji.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. Ten proces jest powtarzany do momentu finally wykonania bloków wszystkich try instrukcji interwencji.This process is repeated until the finally blocks of all intervening try statements have been executed.
  • Kontrolka jest przenoszona do elementu docelowego continue instrukcji.Control is transferred to the target of the continue statement.

Ponieważ continue instrukcja bezwarunkowo transferuje kontrolę w innym miejscu, punkt końcowy continue instrukcji nie jest nigdy osiągalny.Because a continue statement unconditionally transfers control elsewhere, the end point of a continue statement is never reachable.

Instrukcja gotoThe goto statement

gotoInstrukcja przekazuje formant do instrukcji, która jest oznaczona etykietą.The goto statement transfers control to a statement that is marked by a label.

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

Obiekt docelowy goto instrukcji identyfikatora jest instrukcją z etykietą z daną etykietą.The target of a goto identifier statement is the labeled statement with the given label. Jeśli etykieta o danej nazwie nie istnieje w elemencie członkowskim bieżącej funkcji lub jeśli goto instrukcja nie znajduje się w zakresie etykiety, wystąpi błąd w czasie kompilacji.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. Ta reguła umożliwia użycie goto instrukcji w celu przeniesienia kontroli poza zagnieżdżony zakres, ale nie do zakresu zagnieżdżonego.This rule permits the use of a goto statement to transfer control out of a nested scope, but not into a nested scope. W przykładzieIn 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);
        }
    }
}

gotoinstrukcja jest używana do transferowania kontroli poza zagnieżdżony zakres.a goto statement is used to transfer control out of a nested scope.

Obiektem docelowym goto case instrukcji jest lista instrukcji w bezpośrednio otaczającej switch instrukcji (instrukcji switch), która zawiera case etykietę o danej wartości stałej.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. Jeśli goto case instrukcja nie jest ujęta w switch instrukcję, jeśli constant_expression nie jest możliwa do konwersji niejawnie (konwersje niejawne) na typ zasad najbliższej otaczającej switch instrukcji lub Jeśli Najbliższa otaczająca switch instrukcja nie zawiera case etykiety z daną wartością stałą, wystąpi błąd w czasie kompilacji.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.

Obiektem docelowym goto default instrukcji jest lista instrukcji w bezpośrednio otaczającej switch instrukcji (instrukcji switch), która zawiera default etykietę.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. Jeśli goto default instrukcja nie jest ujęta w switch instrukcję lub Jeśli Najbliższa otaczająca instrukcja nie switch zawiera default etykiety, wystąpi błąd w czasie kompilacji.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.

gotoInstrukcja nie może opuścić finally bloku (Instrukcja try).A goto statement cannot exit a finally block (The try statement). Gdy goto instrukcja występuje w finally bloku, obiekt docelowy goto instrukcji musi znajdować się w tym samym finally bloku lub w przeciwnym razie wystąpi błąd w czasie kompilacji.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.

gotoInstrukcja jest wykonywana w następujący sposób:A goto statement is executed as follows:

  • Jeśli goto instrukcja kończy jeden lub więcej try bloków ze skojarzonymi finally blokami, kontrola jest początkowo przekazywana do finally bloku wewnętrznej try instrukcji.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. Gdy i jeśli kontrola osiągnie punkt końcowy finally bloku, sterowanie jest przekazywane do finally bloku następnej otaczającej try instrukcji.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. Ten proces jest powtarzany do momentu finally wykonania bloków wszystkich try instrukcji interwencji.This process is repeated until the finally blocks of all intervening try statements have been executed.
  • Kontrolka jest przenoszona do elementu docelowego goto instrukcji.Control is transferred to the target of the goto statement.

Ponieważ goto instrukcja bezwarunkowo transferuje kontrolę w innym miejscu, punkt końcowy goto instrukcji nie jest nigdy osiągalny.Because a goto statement unconditionally transfers control elsewhere, the end point of a goto statement is never reachable.

Instrukcja returnThe return statement

returnInstrukcja zwraca kontrolę do bieżącego obiektu wywołującego funkcji, w której return występuje instrukcja.The return statement returns control to the current caller of the function in which the return statement appears.

return_statement
    : 'return' expression? ';'
    ;

returnInstrukcja bez wyrażenia może być używana tylko w składowej funkcji, która nie oblicza wartości, czyli metody z typem wyniku (treść metody) void , set akcesorem właściwości lub indeksatora, add dostępem i akcesorami remove zdarzenia, konstruktorem wystąpienia, konstruktorem statycznym lub destruktorem.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.

returnInstrukcji z wyrażeniem można użyć tylko w składowej funkcji, która oblicza wartość, czyli metodę z typem wyniku innym niż void, get akcesorem właściwości lub indeksatorem lub operatorem zdefiniowanym przez użytkownika.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. Niejawna konwersja (niejawne konwersje) musi istnieć z typu wyrażenia do zwracanego typu elementu członkowskiego funkcji zawierającego.An implicit conversion (Implicit conversions) must exist from the type of the expression to the return type of the containing function member.

Instrukcji return można także używać w treści wyrażeń funkcji anonimowych (wyrażenia funkcji anonimowych) i uczestniczyć w ustaleniu, które konwersje istnieją dla tych funkcji.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.

Jest to błąd czasu kompilacji dla return instrukcji, która ma być wyświetlana w finally bloku (Instrukcja try).It is a compile-time error for a return statement to appear in a finally block (The try statement).

returnInstrukcja jest wykonywana w następujący sposób:A return statement is executed as follows:

  • Jeśli return instrukcja określa wyrażenie, wyrażenie jest oceniane i wynikowa wartość jest konwertowana na typ zwracany funkcji zawierającej przez niejawną konwersję.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. Wynik konwersji jest wartością wynikową wygenerowaną przez funkcję.The result of the conversion becomes the result value produced by the function.
  • Jeśli return instrukcja jest ujęta w jeden lub więcej try lub catch bloków ze skojarzonymi finally blokami, kontrola jest początkowo przekazywana do finally bloku wewnętrznej try instrukcji.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. Gdy i jeśli kontrola osiągnie punkt końcowy finally bloku, sterowanie jest przekazywane do finally bloku następnej otaczającej try instrukcji.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. Ten proces jest powtarzany do momentu finally wykonania bloków wszystkich try instrukcji otaczających.This process is repeated until the finally blocks of all enclosing try statements have been executed.
  • Jeśli funkcja zawierająca nie jest funkcją asynchroniczną, formant jest zwracany do obiektu wywołującego funkcji zawierającej wraz z wartością wyniku (jeśli istnieje).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.
  • Jeśli funkcja zawierająca jest funkcją asynchroniczną, formant jest zwracany do bieżącego obiektu wywołującego, a wartość wynikowa (jeśli istnieje) jest rejestrowana w zadaniu zwrotnym, zgodnie z opisem w temacie (moduły wyliczające).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).

Ponieważ return instrukcja bezwarunkowo transferuje kontrolę w innym miejscu, punkt końcowy return instrukcji nie jest nigdy osiągalny.Because a return statement unconditionally transfers control elsewhere, the end point of a return statement is never reachable.

Instrukcja throwThe throw statement

throwInstrukcja zgłasza wyjątek.The throw statement throws an exception.

throw_statement
    : 'throw' expression? ';'
    ;

throwInstrukcja z wyrażeniem zwraca wartość wygenerowaną przez obliczenie wyrażenia.A throw statement with an expression throws the value produced by evaluating the expression. Wyrażenie musi wskazywać wartość typu klasy w System.Exception typie klasy, który pochodzi od System.Exception lub typu parametru typu, który ma System.Exception (lub podklasę) jako obowiązującą klasę bazową.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. Jeśli zostanie wygenerowane obliczenie wyrażenia null , w System.NullReferenceException zamian zostanie zgłoszony.If evaluation of the expression produces null, a System.NullReferenceException is thrown instead.

throwInstrukcja bez wyrażenia może być używana tylko w catch bloku, w takim przypadku instrukcja ponownie zgłasza wyjątek, który jest obecnie obsługiwany przez ten catch blok.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.

Ponieważ throw instrukcja bezwarunkowo transferuje kontrolę w innym miejscu, punkt końcowy throw instrukcji nie jest nigdy osiągalny.Because a throw statement unconditionally transfers control elsewhere, the end point of a throw statement is never reachable.

Gdy wyjątek jest zgłaszany, kontrola jest przekazywana do pierwszej catch klauzuli w otaczającej try instrukcji, która może obsłużyć wyjątek.When an exception is thrown, control is transferred to the first catch clause in an enclosing try statement that can handle the exception. Proces, który ma miejsce od momentu, gdy wyjątek zgłaszany do punktu transferu kontroli do odpowiedniej procedury obsługi wyjątków jest znany jako *Propagacja wyjątku _.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 _. Propagacja wyjątku polega na wielokrotnym ocenie następujących kroków do momentu catch znalezienia klauzuli zgodnej z wyjątkiem.Propagation of an exception consists of repeatedly evaluating the following steps until a catch clause that matches the exception is found. W tym opisie _ w punkcie throw* jest początkowo lokalizacją, w której został zgłoszony wyjątek.In this description, the _ throw point* is initially the location at which the exception is thrown.

  • W bieżącym elemencie członkowskim funkcji try są badane wszystkie instrukcje, które obejmują punkt throw.In the current function member, each try statement that encloses the throw point is examined. Dla każdej instrukcji S , zaczynając od najbardziej wewnętrznej try instrukcji i kończąc na zewnętrznej try instrukcji, oceniane są następujące kroki:For each statement S, starting with the innermost try statement and ending with the outermost try statement, the following steps are evaluated:

    • Jeśli try blok S ujmowania punktu rzutowania i jeśli S ma jedną catch klauzulę, catch klauzule są badane w kolejności występowania, aby znaleźć odpowiednią procedurę obsługi dla wyjątku, zgodnie z regułami określonymi w sekcji try instrukcji.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. Jeśli znajduje się catch klauzula dopasowywania, Propagacja wyjątku jest wykonywana przez przeniesienie kontroli do bloku tej catch klauzuli.If a matching catch clause is located, the exception propagation is completed by transferring control to the block of that catch clause.

    • W przeciwnym razie, jeśli try blok lub catch blok S otaczający punkt rzutowania i jeśli S ma finally blok, sterowanie jest przekazywane do finally bloku.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. Jeśli finally blok zgłasza inny wyjątek, przetwarzanie bieżącego wyjątku zostanie zakończone.If the finally block throws another exception, processing of the current exception is terminated. W przeciwnym razie, gdy formant osiągnie punkt końcowy finally bloku, przetwarzanie bieżącego wyjątku jest kontynuowane.Otherwise, when control reaches the end point of the finally block, processing of the current exception is continued.

  • Jeśli program obsługi wyjątków nie znajduje się w bieżącym wywołaniu funkcji, wywołanie funkcji jest przerywane i jedna z następujących sytuacji:If an exception handler was not located in the current function invocation, the function invocation is terminated, and one of the following occurs:

    • Jeśli bieżąca funkcja nie jest asynchroniczna, powyższe kroki są powtórzone dla obiektu wywołującego funkcji z punktem rzutowania odpowiadającym instrukcji, z której wywołano element członkowski funkcji.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.

    • Jeśli bieżąca funkcja jest asynchroniczna i zwracająca zadania, wyjątek jest rejestrowany w zadaniu zwrotnym, które jest umieszczane w stanie awarii lub anulowania zgodnie z opisem w temacie interfejsy modułu wyliczającego.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.

    • Jeśli bieżąca funkcja ma wartość Async i zwraca wartość void, kontekst synchronizacji bieżącego wątku zostanie powiadomiony zgodnie z opisem w wyliczalnych interfejsach.If the current function is async and void-returning, the synchronization context of the current thread is notified as described in Enumerable interfaces.

  • Jeśli przetwarzanie wyjątku kończy wszystkie wywołania elementu członkowskiego funkcji w bieżącym wątku, wskazując, że wątek nie ma obsługi dla wyjątku, wątek jest zakończony.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. Wpływ tego zakończenia jest zdefiniowany przez implementację.The impact of such termination is implementation-defined.

Instrukcja tryThe try statement

tryInstrukcja zawiera mechanizm przechwytywania wyjątków, które występują podczas wykonywania bloku.The try statement provides a mechanism for catching exceptions that occur during execution of a block. Ponadto try instrukcja umożliwia określenie bloku kodu, który jest zawsze wykonywany, gdy kontrolka opuszcza try instrukcję.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
    ;

Istnieją trzy możliwe formy try instrukcji:There are three possible forms of try statements:

  • tryBlok, po którym następuje co najmniej jeden blok catch .A try block followed by one or more catch blocks.
  • tryBlok, po którym następuje finally blok.A try block followed by a finally block.
  • Blok, po którym następuje try jeden lub więcej catch bloków, po którym następuje finally blok.A try block followed by one or more catch blocks followed by a finally block.

Gdy catch klauzula określa exception_specifier, typem musi być System.Exception , typ, który pochodzi od System.Exception lub typu parametru typu, który ma System.Exception (lub podklasę tej klasy) jako obowiązującą klasę bazową.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.

Gdy catch klauzula określa exception_specifier z identyfikatorem, zadeklarowana jest zmienna wyjątku* o podanej nazwie i typie.When a catch clause specifies both an exception_specifier with an identifier, an *exception variable _ of the given name and type is declared. Zmienna wyjątku odpowiada zmiennej lokalnej z zakresem, który wykracza poza catch klauzulę.The exception variable corresponds to a local variable with a scope that extends over the catch clause. Podczas wykonywania _exception_filter * i bloku zmienna wyjątku reprezentuje aktualnie obsługiwany wyjątek.During execution of the _exception_filter* and block, the exception variable represents the exception currently being handled. W celach o określonym zapisywaniu zmienna wyjątku jest uznawana za ostatecznie przypisaną w całym zakresie.For purposes of definite assignment checking, the exception variable is considered definitely assigned in its entire scope.

O ile catch klauzula nie zawiera nazwy zmiennej wyjątku, nie można uzyskać dostępu do obiektu Exception w filtrze i catch bloku.Unless a catch clause includes an exception variable name, it is impossible to access the exception object in the filter and catch block.

catchKlauzula, która nie określa exception_specifier jest nazywana catch klauzulą Generalną.A catch clause that does not specify an exception_specifier is called a general catch clause.

Niektóre języki programowania mogą obsługiwać wyjątki, które nie są reprezentowane jako obiekt pochodny System.Exception , chociaż takie wyjątki nigdy nie mogą być generowane przez kod C#.Some programming languages may support exceptions that are not representable as an object derived from System.Exception, although such exceptions could never be generated by C# code. Klauzula General catch może służyć do przechwytywania takich wyjątków.A general catch clause may be used to catch such exceptions. W rezultacie Klauzula ogólna catch jest semantycznie różna od jednej, która określa typ System.Exception , w tym, że dawny może również przechwytywać wyjątki z innych języków.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.

Aby zlokalizować procedurę obsługi dla wyjątku, catch klauzule są badane w kolejności leksykalnej.In order to locate a handler for an exception, catch clauses are examined in lexical order. Jeśli catch klauzula określa typ, ale nie filtr wyjątku, jest to błąd czasu kompilacji dla późniejszej catch klauzuli w tej samej try instrukcji, aby określić typ, który jest taki sam jak lub pochodzi od typu.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. Jeśli catch klauzula nie określa typu ani filtru, musi być ostatnią catch klauzulą tej try instrukcji.If a catch clause specifies no type and no filter, it must be the last catch clause for that try statement.

W catch bloku throw instrukcja (Instrukcja throw) bez wyrażenia może służyć do ponownego zgłoszenia wyjątku, który został przechwycony przez catch blok.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. Przypisania do zmiennej wyjątku nie powodują zmiany zgłoszonego wyjątku.Assignments to an exception variable do not alter the exception that is re-thrown.

W przykładzieIn 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);
        }
    }
}

Metoda F przechwytuje wyjątek, zapisuje niektóre informacje diagnostyczne do konsoli, modyfikuje zmienną wyjątku i ponowne zgłasza wyjątek.the method F catches an exception, writes some diagnostic information to the console, alters the exception variable, and re-throws the exception. Wyjątek, który jest ponownie zgłaszany, to oryginalny wyjątek, dlatego utworzony wynik to:The exception that is re-thrown is the original exception, so the output produced is:

Exception in F: G
Exception in Main: G

Jeśli pierwszy blok catch został zgłoszony zamiast ponownego zgłoszenia e bieżącego wyjątku, utworzone dane wyjściowe byłyby następujące: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

Jest to błąd czasu kompilacji dla break instrukcji, lub, continue goto Aby przenieść kontrolę z finally bloku.It is a compile-time error for a break, continue, or goto statement to transfer control out of a finally block. Gdy break instrukcja, continue , lub goto występuje w finally bloku, obiekt docelowy instrukcji musi znajdować się w tym samym finally bloku lub w przeciwnym razie wystąpi błąd w czasie kompilacji.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.

Jest to błąd czasu kompilacji dla return instrukcji, która ma być wykonywana w finally bloku.It is a compile-time error for a return statement to occur in a finally block.

tryInstrukcja jest wykonywana w następujący sposób:A try statement is executed as follows:

  • Kontrolka jest przenoszona do try bloku.Control is transferred to the try block.

  • Gdy i jeśli kontrola osiągnie punkt końcowy try bloku:When and if control reaches the end point of the try block:

    • Jeśli try instrukcja zawiera finally blok, finally zostaje wykonany blok.If the try statement has a finally block, the finally block is executed.
    • Kontrolka jest przenoszona do punktu końcowego try instrukcji.Control is transferred to the end point of the try statement.
  • Jeśli wyjątek jest propagowany do try instrukcji podczas wykonywania try bloku:If an exception is propagated to the try statement during execution of the try block:

    • catchKlauzule, jeśli istnieją, są badane w kolejności występowania, aby znaleźć odpowiednią procedurę obsługi dla wyjątku.The catch clauses, if any, are examined in order of appearance to locate a suitable handler for the exception. Jeśli catch klauzula nie określa typu lub określa typ wyjątku lub typ podstawowy typu wyjątku:If a catch clause does not specify a type, or specifies the exception type or a base type of the exception type:
      • Jeśli catch klauzula deklaruje zmienną wyjątku, obiekt wyjątku jest przypisywany do zmiennej wyjątku.If the catch clause declares an exception variable, the exception object is assigned to the exception variable.
      • Jeśli catch klauzula deklaruje filtr wyjątku, filtr jest obliczany.If the catch clause declares an exception filter, the filter is evaluated. Jeśli wartość jest równa false , klauzula catch nie jest zgodna i wyszukiwanie kontynuuje się przez wszelkie kolejne catch klauzule dla odpowiedniej procedury obsługi.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.
      • W przeciwnym razie catch klauzula jest uważana za dopasowanie, a kontrola jest przekazywana do zgodnego catch bloku.Otherwise, the catch clause is considered a match, and control is transferred to the matching catch block.
      • Gdy i jeśli kontrola osiągnie punkt końcowy catch bloku:When and if control reaches the end point of the catch block:
        • Jeśli try instrukcja zawiera finally blok, finally zostaje wykonany blok.If the try statement has a finally block, the finally block is executed.
        • Kontrolka jest przenoszona do punktu końcowego try instrukcji.Control is transferred to the end point of the try statement.
      • Jeśli wyjątek jest propagowany do try instrukcji podczas wykonywania catch bloku:If an exception is propagated to the try statement during execution of the catch block:
        • Jeśli try instrukcja zawiera finally blok, finally zostaje wykonany blok.If the try statement has a finally block, the finally block is executed.
        • Wyjątek jest propagowany do następnej otaczającej try instrukcji.The exception is propagated to the next enclosing try statement.
    • Jeśli try instrukcja nie ma catch klauzul lub jeśli żadna klauzula nie catch pasuje do wyjątku:If the try statement has no catch clauses or if no catch clause matches the exception:
      • Jeśli try instrukcja zawiera finally blok, finally zostaje wykonany blok.If the try statement has a finally block, the finally block is executed.
      • Wyjątek jest propagowany do następnej otaczającej try instrukcji.The exception is propagated to the next enclosing try statement.

Instrukcje finally bloku są zawsze wykonywane, gdy kontrolka opuszcza try instrukcję.The statements of a finally block are always executed when control leaves a try statement. Jest to prawdą, czy transfer kontrolny występuje w wyniku normalnego wykonywania, w wyniku wykonywania break continue instrukcji,, goto , lub return w wyniku propagacji wyjątku z try instrukcji.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.

Jeśli wyjątek jest zgłaszany podczas wykonywania finally bloku i nie jest przechwytywany w obrębie tego samego bloku finally, wyjątek jest propagowany do następnej otaczającej try instrukcji.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. Jeśli inny wyjątek był w trakcie propagowania, ten wyjątek zostanie utracony.If another exception was in the process of being propagated, that exception is lost. Proces propagowania wyjątku jest dokładniej opisany w opisie throw instrukcji (Instrukcja throw).The process of propagating an exception is discussed further in the description of the throw statement (The throw statement).

tryBlok try instrukcji jest osiągalny, jeśli try instrukcja jest osiągalna.The try block of a try statement is reachable if the try statement is reachable.

catchBlok try instrukcji jest osiągalny, jeśli try instrukcja jest osiągalna.A catch block of a try statement is reachable if the try statement is reachable.

finallyBlok try instrukcji jest osiągalny, jeśli try instrukcja jest osiągalna.The finally block of a try statement is reachable if the try statement is reachable.

Punkt końcowy try instrukcji jest osiągalny, jeśli są spełnione oba poniższe warunki:The end point of a try statement is reachable if both of the following are true:

  • Punkt końcowy try bloku jest osiągalny lub punkt końcowy co najmniej jednego catch bloku jest osiągalny.The end point of the try block is reachable or the end point of at least one catch block is reachable.
  • Jeśli znajduje finally się blok, punkt końcowy finally bloku jest osiągalny.If a finally block is present, the end point of the finally block is reachable.

Sprawdzone i niesprawdzone instrukcjeThe checked and unchecked statements

checkedInstrukcje and unchecked są używane do kontrolowania kontekstu sprawdzania przepełnienia dla operacji arytmetycznych typu całkowitego i konwersji.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
    ;

checkedInstrukcja powoduje, że wszystkie wyrażenia w bloku są oceniane w kontekście sprawdzonym, a unchecked instrukcja powoduje, że wszystkie wyrażenia w bloku są oceniane w niesprawdzonym kontekście.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.

checkedInstrukcje and unchecked są precyzyjnie równoważne checked unchecked operatorom and (Operatory sprawdzone i niezaznaczone), z tą różnicą, że działają na blokach zamiast wyrażeń.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.

Instrukcja lockThe lock statement

lockInstrukcja uzyskuje blokadę wykluczania wzajemnego dla danego obiektu, wykonuje instrukcję, a następnie zwalnia blokadę.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
    ;

Wyrażenie lock instrukcji musi wskazywać wartość typu znanego jako reference_type.The expression of a lock statement must denote a value of a type known to be a reference_type. Żadna niejawna konwersja opakowania (konwersjenapakowywania) nie jest kiedykolwiek wykonywana dla wyrażenia lock instrukcji i w ten sposób jest to błąd czasu kompilacji dla wyrażenia, aby zauważyć wartość value_type.No implicit boxing conversion (Boxing conversions) is ever performed for the expression of a lock statement, and thus it is a compile-time error for the expression to denote a value of a value_type.

lockInstrukcja formularzaA lock statement of the form

lock (x) ...

gdzie x jest wyrażeniem reference_type, jest dokładnie równoważnewhere 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);
}

z tą różnicą, że x jest obliczana tylko raz.except that x is only evaluated once.

Gdy blokada wzajemnego wykluczania jest utrzymywana, kod wykonywany w tym samym wątku wykonywania może również uzyskać i zwolnić blokadę.While a mutual-exclusion lock is held, code executing in the same execution thread can also obtain and release the lock. Jednak kod wykonywany w innych wątkach ma zablokowany dostęp do blokady do momentu zwolnienia blokady.However, code executing in other threads is blocked from obtaining the lock until the lock is released.

Blokowanie System.Type obiektów w celu synchronizacji dostępu do danych statycznych nie jest zalecane.Locking System.Type objects in order to synchronize access to static data is not recommended. Inny kod może być zablokowany dla tego samego typu, co może spowodować zakleszczenie.Other code might lock on the same type, which can result in deadlock. Lepszym rozwiązaniem jest synchronizowanie dostępu do danych statycznych przez zablokowanie prywatnego obiektu statycznego.A better approach is to synchronize access to static data by locking a private static object. Na przykład: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) {
            ...
        }
    }
}

Instrukcja usingThe using statement

usingInstrukcja uzyskuje jeden lub więcej zasobów, wykonuje instrukcję, a następnie usuwa zasób.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
    ;

Zasób jest klasą lub strukturą, która implementuje System.IDisposable , która zawiera pojedynczą metodę bez parametrów o nazwie Dispose .A resource is a class or struct that implements System.IDisposable, which includes a single parameterless method named Dispose. Kod używający zasobu może wywoływać Dispose , aby wskazać, że zasób nie jest już wymagany.Code that is using a resource can call Dispose to indicate that the resource is no longer needed. Jeśli Dispose nie jest wywoływana, automatyczne usuwanie następuje ostatecznie w wyniku wyrzucania elementów bezużytecznych.If Dispose is not called, then automatic disposal eventually occurs as a consequence of garbage collection.

Jeśli forma resource_acquisition jest local_variable_declaration , typem local_variable_declaration musi być albo dynamic lub typ, który można niejawnie przekonwertować na System.IDisposable .If the form of resource_acquisition is local_variable_declaration then the type of the local_variable_declaration must be either dynamic or a type that can be implicitly converted to System.IDisposable. Jeśli jest wyrażeniem resource_acquisition , to wyrażenie musi być niejawnie konwertowane na System.IDisposable .If the form of resource_acquisition is expression then this expression must be implicitly convertible to System.IDisposable.

Zmienne lokalne zadeklarowane w resource_acquisition są tylko do odczytu i muszą zawierać inicjator.Local variables declared in a resource_acquisition are read-only, and must include an initializer. Błąd czasu kompilacji występuje, jeśli osadzona instrukcja próbuje zmodyfikować te zmienne lokalne (poprzez przypisanie lub ++ -- Operatory i), pobrać ich adresy lub przekazać je jako ref lub out parametry.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.

usingInstrukcja jest tłumaczona na trzy części: pozyskiwanie, użycie i usuwanie.A using statement is translated into three parts: acquisition, usage, and disposal. Użycie zasobu jest niejawnie ujęte w try instrukcji, która zawiera finally klauzulę.Usage of the resource is implicitly enclosed in a try statement that includes a finally clause. Ta finally klauzula usuwa zasób.This finally clause disposes of the resource. Jeśli null zasób zostanie uzyskany, żadne wywołanie nie Dispose zostanie wykonane i żaden wyjątek nie jest zgłaszany.If a null resource is acquired, then no call to Dispose is made, and no exception is thrown. Jeśli zasób jest typu, dynamic jest dynamicznie konwertowany przy użyciu niejawnej konwersji dynamicznej (niejawne konwersje dynamiczne) do IDisposable podczas pozyskiwania w celu zapewnienia, że konwersja zakończy się pomyślnie przed użyciem i usuwaniem.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.

usingInstrukcja formularzaA using statement of the form

using (ResourceType resource = expression) statement

odpowiada jednemu z trzech możliwych rozszerzeń.corresponds to one of three possible expansions. Gdy ResourceType jest typem wartości niedopuszczających wartości null, rozszerzenie jestWhen ResourceType is a non-nullable value type, the expansion is

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

W przeciwnym razie, gdy ResourceType jest typem wartości null lub typem odwołania innym niż dynamic , rozszerzenie jestOtherwise, 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();
    }
}

W przeciwnym razie ResourceType dynamic rozszerzenie jestOtherwise, when ResourceType is dynamic, the expansion is

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

W obu rozszerzeniach resource zmienna jest tylko do odczytu w osadzonej instrukcji, a d zmienna jest niedostępna w, i niewidoczna dla, osadzonej instrukcji.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.

Implementacja może implementować daną instrukcję using inaczej, np. ze względu na wydajność, o ile zachowanie jest spójne z powyższym rozszerzeniem.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.

usingInstrukcja formularzaA using statement of the form

using (expression) statement

ma te same trzy możliwe rozszerzenia.has the same three possible expansions. W tym przypadku ResourceType jest niejawnie typem czasu kompilacji expression , jeśli ma.In this case ResourceType is implicitly the compile-time type of the expression, if it has one. W przeciwnym razie IDisposable sam interfejs jest używany jako ResourceType .Otherwise the interface IDisposable itself is used as the ResourceType. resourceZmienna jest niedostępna w, i niewidoczna dla osadzonej instrukcji.The resource variable is inaccessible in, and invisible to, the embedded statement.

Gdy resource_acquisition ma formę local_variable_declaration, możliwe jest uzyskanie wielu zasobów danego typu.When a resource_acquisition takes the form of a local_variable_declaration, it is possible to acquire multiple resources of a given type. usingInstrukcja formularzaA using statement of the form

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

jest precyzyjnym odpowiednikiem sekwencji zagnieżdżonych using instrukcji:is precisely equivalent to a sequence of nested using statements:

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

Poniższy przykład tworzy plik o nazwie log.txt i zapisuje dwa wiersze tekstu do pliku.The example below creates a file named log.txt and writes two lines of text to the file. W tym przykładzie zostanie otwarty ten sam plik do odczytu i kopiowania zawartych wierszy tekstu do konsoli programu.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);
            }

        }
    }
}

Ponieważ TextWriter klasy i TextReader implementują IDisposable interfejs, przykład może używać instrukcji, using Aby upewnić się, że plik źródłowy jest prawidłowo zamknięty po operacji zapisu lub odczytu.Since the TextWriter and TextReader classes implement the IDisposable interface, the example can use using statements to ensure that the underlying file is properly closed following the write or read operations.

Instrukcja YieldThe yield statement

yieldInstrukcja jest używana w bloku iteratora (bloki) do przesyłania wartości do obiektu modułu wyliczającego (obiektów modułu wyliczającego) lub wyliczalnego obiektu (obiektów wyliczalnych) iteratora lub do sygnalizowania końcem iteracji.The yield statement is used in an iterator block (Blocks) to yield a value to the enumerator object (Enumerator objects) or enumerable object (Enumerable objects) of an iterator or to signal the end of the iteration.

yield_statement
    : 'yield' 'return' expression ';'
    | 'yield' 'break' ';'
    ;

yield nie jest słowem zastrzeżonym; ma specjalne znaczenie tylko wtedy, gdy jest używana bezpośrednio return przed break słowem kluczowym or.yield is not a reserved word; it has special meaning only when used immediately before a return or break keyword. W innych kontekstach yield można użyć jako identyfikatora.In other contexts, yield can be used as an identifier.

Istnieje kilka ograniczeń w miejscu, w którym yield instrukcja może zostać wyświetlona, zgodnie z opisem w poniższej tabeli.There are several restrictions on where a yield statement can appear, as described in the following.

  • Jest to błąd czasu kompilacji dla yield instrukcji (każdej z formularzy), która ma być wyświetlana poza method_body, operator_body lub accessor_bodyIt is a compile-time error for a yield statement (of either form) to appear outside a method_body, operator_body or accessor_body
  • Jest to błąd czasu kompilacji dla yield instrukcji (każdej z formularzy), która ma być wyświetlana wewnątrz funkcji anonimowej.It is a compile-time error for a yield statement (of either form) to appear inside an anonymous function.
  • Jest to błąd czasu kompilacji dla yield instrukcji (każdej z formularzy) do wyświetlenia w finally klauzuli try instrukcji.It is a compile-time error for a yield statement (of either form) to appear in the finally clause of a try statement.
  • Jest to błąd czasu kompilacji dla yield return instrukcji pojawia się gdziekolwiek w try instrukcji, która zawiera catch klauzule.It is a compile-time error for a yield return statement to appear anywhere in a try statement that contains any catch clauses.

W poniższym przykładzie przedstawiono nieprawidłowe i nieprawidłowe zastosowania yield instrukcji.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
}

Niejawna konwersja (niejawne konwersje) musi istnieć z typu wyrażenia w yield return instrukcji do typu yield (Typ Yield) iteratora.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.

yield returnInstrukcja jest wykonywana w następujący sposób:A yield return statement is executed as follows:

  • Wyrażenie określone w instrukcji jest oceniane, niejawnie konwertowane na typ Yield i przypisywane do Current właściwości obiektu modułu wyliczającego.The expression given in the statement is evaluated, implicitly converted to the yield type, and assigned to the Current property of the enumerator object.
  • Wykonywanie bloku iteratora zostało wstrzymane.Execution of the iterator block is suspended. Jeśli yield return instrukcja znajduje się w jednym lub większej liczbie try bloków, skojarzone finally bloki nie są wykonywane w tym momencie.If the yield return statement is within one or more try blocks, the associated finally blocks are not executed at this time.
  • MoveNextMetoda obiektu Enumerator powraca true do jego obiektu wywołującego, wskazując, że obiekt Enumerator został pomyślnie zaawansowany do następnego elementu.The MoveNext method of the enumerator object returns true to its caller, indicating that the enumerator object successfully advanced to the next item.

Następne wywołanie metody obiektu modułu wyliczającego MoveNext wznawia wykonywanie bloku iteratora od momentu ostatniego wstrzymania.The next call to the enumerator object's MoveNext method resumes execution of the iterator block from where it was last suspended.

yield breakInstrukcja jest wykonywana w następujący sposób:A yield break statement is executed as follows:

  • Jeśli yield break instrukcja jest ujęta w jeden lub więcej try bloków ze skojarzonymi finally blokami, kontrola jest początkowo przekazywana do finally bloku wewnętrznej try instrukcji.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. Gdy i jeśli kontrola osiągnie punkt końcowy finally bloku, sterowanie jest przekazywane do finally bloku następnej otaczającej try instrukcji.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. Ten proces jest powtarzany do momentu finally wykonania bloków wszystkich try instrukcji otaczających.This process is repeated until the finally blocks of all enclosing try statements have been executed.
  • Formant jest zwracany do obiektu wywołującego bloku iteratora.Control is returned to the caller of the iterator block. Jest to MoveNext Metoda lub Dispose Metoda obiektu modułu wyliczającego.This is either the MoveNext method or Dispose method of the enumerator object.

Ponieważ yield break instrukcja bezwarunkowo transferuje kontrolę w innym miejscu, punkt końcowy yield break instrukcji nie jest nigdy osiągalny.Because a yield break statement unconditionally transfers control elsewhere, the end point of a yield break statement is never reachable.