InstrukcjeStatements

C#zawiera różne instrukcje.C# provides a variety of statements. Większość z tych instrukcji będzie znana deweloperom, którzy zaprogramowany w języku 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 nie jest używany do 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;
}

wynikiem jest błąd czasu kompilacji, ponieważ instrukcja if 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 ideklaracji 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 jest możliwe, że instrukcja zostanie wykonana, instrukcja jest określana jako nieosiągalna.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 if logiczne 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 i jednak 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.WriteLine wywoł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.
  • Instrukcja jest osiągalna, ponieważ punkt końcowy pierwszej Console.WriteLine instrukcji wyrażenia jest osiągalny. ifThe 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 if logiczne instrukcji nie 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:

  • switch Ponieważ 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 jednej lub kilku instrukcji utworzonych w sekwencji.A statement list consists of one or more statements written in sequence. Listy instrukcji występują w blokach blokus (bloki) i w switch_blocks (instrukcja SWITCH).Statement lists occur in blocks (Blocks) and in switch_blocks (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ę goto osiągalną.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 poprzedzonej 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ę goto z 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, goto że 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. Oprócz finally try finally Jeśli instrukcja znajduje się wewnątrz, try która zawiera blok, a instrukcja z etykietą jest poza, a punkt końcowy bloku jest nieosiągalny, a następnie instrukcja z etykietą nie jest dostępna od goto 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, że typ powinien być 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_declarators, z których każdy wprowadza nową zmienną.The type is followed by a list of local_variable_declarators, 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óry 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). Jeśli local_variable_type jest określony jako var i żaden typ o nazwie var znajduje się 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_declarators.The local_variable_declaration cannot include multiple local_variable_declarators.
  • Local_variable_declarator musi zawierać element 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_declarators, z których każdy wprowadza nową stałą.The type is followed by a list of constant_declarators, each of which introduces a new constant. Constant_declarator składa się z identyfikatora , który nadaje nazwę stałemu, po którym następuje token "=", po którym następuje constant_expression (wyrażenia stałe), które dają 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 przypadku 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 elementu simple_name (Simple Names).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 określone wyrażenie.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 elementu expression_statement powoduje oszacowanie zawartego wyrażenia, a następnie przekazanie kontroli 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 osiągalny, 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

if Instrukcja 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
    ;

Część jest skojarzona z leksykalną najbliższą poprzednią if , która jest dozwolona przez składnię. elseAn 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();

odpowiada wyrażeniuis equivalent to

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

if Instrukcja 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 if końcowego 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 false wartość i else jeśli 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 if końcowego 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 false wartość i else jeśli część nie istnieje, kontrola jest przekazywana do punktu if końcowego 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, if Jeśli 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, if Jeśli 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 if końcowy 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 if końcowy instrukcji bez else if części jest osiągalny, jeśli 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, a następnie wyrażenia ujętego w nawiasy (nazywanego 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_sections ujętych w nawiasy klamrowe.The switch_block consists of zero or more switch_sections, enclosed in braces. Każdy switch_section składa się z jednego lub więcej switch_labels, po których następuje statement_list (Lista instrukcji).Each switch_section consists of one or more switch_labels followed by a statement_list (Statement lists).

Typswitch rządzący 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, 0 lub typudopuszczającego wartość null odpowiadającego jednemu z tych typów , a następnie jest to typ rządzący instrukcji 2.If the type of the switch expression is sbyte, byte, short, ushort, int, uint, long, ulong, bool, char, string, or an enum_type, or if it is the nullable type corresponding to one of these types, then that is the governing type of the switch statement.
  • 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 rodzajów typów: sbyte, byte, short, ushort , int uint, ,,string,, lub, typu dopuszczającego wartość null odpowiadającego jednemu z tych typów. long ulong charOtherwise, 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 switch decydujący 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 case najmniej dwie 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 default najwyżej jedna etykieta.There can be at most one default label in a switch statement.

switch Instrukcja 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 case w etykietach w tej samej switch instrukcji nie jest równa wartości default wyrażenia Switch i jeśli etykieta jest obecna, sterowanie default jest przekazywane do listy instrukcji po oznakowan.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 case w etykietach w tej samej switch instrukcji nie jest równa wartości wyrażenia Switch i jeśli żadna etykieta nie default jest obecna, kontrola switch jest przekazywana do punktu końcowego 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 C++języka C i wykonywanie sekcji Switch nie jest dozwolone w sekcji "przechodzenie" do następnego przełącznika i przykładUnlike 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 musi być użyta jawna goto case instrukcja or: goto defaultWhen 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_sectionjest 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_sectionu.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 języku C oraz przypadki C++ , break w których 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 switch przełącznika 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 breakinstrukcji, goto case, 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 true logiczne 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, instrukcja throw 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 switch decydujący 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_lists switch_block może zawierać instrukcje deklaracji (instrukcje deklaracji).The statement_lists 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ą case z 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 case żadną etykietą, a sekcja Switch default zawiera 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 instrukcja goto default or.A switch label of the switch section is referenced by a reachable goto case or goto default statement.

Punkt switch końcowy 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:

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

while Instrukcja 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
    ;

while Instrukcja 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 while końcowego instrukcji.If the boolean expression yields false, control is transferred to the end point of the while statement.

W osadzonej instrukcji while instrukcji break instrukcja (instrukcja break) może być używana do transferowania while kontroli do punktu końcowego instrukcji (w związku z tym kończącej iterację osadzonej instrukcji) i continue instrukcja (Instrukcja continue) może być używana do transferowania kontroli do punktu końcowego osadzonej instrukcji (w związku z tym wykonywanie innej while iteracji 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, while Jeśli 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 while końcowy 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:

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

Instrukcja doThe do statement

do Instrukcja 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 ')' ';'
    ;

do Instrukcja 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 wykonywania instrukcji continue), Boolean_expression (wyrażenie logiczne) jest oceniane.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 do końcowego instrukcji.Otherwise, control is transferred to the end point of the do statement.

W osadzonej instrukcji do instrukcji break instrukcja (instrukcja break) może być używana do transferowania do kontroli do punktu końcowego instrukcji (w związku z tym kończącej iterację osadzonej instrukcji) i continue instrukcja (Instrukcja continue) może służyć 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, do Jeśli instrukcja jest osiągalna.The embedded statement of a do statement is reachable if the do statement is reachable.

Punkt do końcowy 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:

  • Instrukcja zawiera break osiągalnądo instrukcję, która kończy wykonywanie instrukcji. doThe 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

for Instrukcja 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_expressions (instrukcje wyrażeń) oddzielone przecinkami.The for_initializer, if present, consists of either a local_variable_declaration (Local variable declarations) or a list of statement_expressions (Expression statements) separated by commas. 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żenie 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_expressions (instrukcje wyrażeń) oddzielone przecinkami.The for_iterator, if present, consists of a list of statement_expressions (Expression statements) separated by commas.

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

  • Jeśli for_initializer jest obecny, 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 for_condition jest obecny, zostanie ona oceniona.If a for_condition is present, it is evaluated.
  • Jeśli for_condition nie istnieje lub w przypadku oszacowania 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 kontrolka osiągnie punkt końcowy osadzonej instrukcji (prawdopodobnie z wykonywania instrukcji continue), wyrażenia for_iterator(jeśli istnieją) są oceniane w sekwencji, a następnie wykonywana jest inna iteracja, rozpoczynając od Obliczanie 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 Ocena false, kontrola jest przekazywana do punktu końcowego instrukcji for.If the for_condition is present and the evaluation yields false, control is transferred to the end point of the for statement.

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

  • Instrukcja for jest dostępna i nie ma for_condition .The for statement is reachable and no for_condition is present.
  • Instrukcja for jest osiągalna, a for_condition jest obecna 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 for końcowy 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:

  • Instrukcja zawiera break osiągalnąfor instrukcję, która kończy wykonywanie instrukcji. forThe for statement contains a reachable break statement that exits the for statement.
  • Instrukcja for jest osiągalna, a for_condition jest obecna 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

foreach Instrukcja 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 zmienną iteracji instrukcji.The type and identifier of a foreach statement declare the iteration variable of the statement. Jeśli identyfikator var jest określony jako local_variable_type, a typ o nazwie var nie należy do zakresu, Zmienna iteracji jest określana jako Zmienna iteracji niejawnie wpisanej, a jej typ jest traktowany jako typ elementu foreach Instrukcja, 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 parametr lub out .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 IEnumerable<T> , IEnumeratori IEnumerator<T> zapoznaj się z 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 instrukcji foreach w czasie kompilacji 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 X typ wyrażenia jest typem tablicy, istnieje niejawna X IEnumerable konwersja odwołania z do 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). Typem kolekcji jest IEnumerable interfejs, typem modułu wyliczającego jest IEnumerator interfejs, a Typ Xelementu jest typem elementu typu tablicy.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.

  • X Jeśli typem wyrażenia jest dynamic ,istniejeniejawnakonwersjazwyrażeniadointerfejsu(niejawnekonwersjedynamiczne).IEnumerable 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 identyfikator var jest określony jako local_variable_type , typ elementu to dynamic, w przeciwnym razie jest 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 X typ 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 E wykonywane na z Current identyfikatorem 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 E wykonywane na z MoveNext identyfikatorem 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 boolbłą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 to X, Typ Emodułu wyliczającego, Current a Typ elementu to typ 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 Ti typów, dla których istnieje niejawna konwersja z X do na IEnumerable<Ti>, istnieje unikatowy typ T , który T nie dynamic jest i dla wszystkich innych Ti niejawna IEnumerable<T> konwersja IEnumerable<Ti>z na, a następnie Typ kolekcji to IEnumerable<T>interfejs, typem modułu wyliczającego jest interfejs IEnumerator<T>, a typem elementu jest 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 Ttyp, 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 X konwersja z System.Collections.IEnumerable do interfejsu, typem kolekcji jest ten interfejs, typem modułu wyliczającego jest interfejs System.Collections.IEnumerator, a typem elementu jest 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 Ckolekcji, typ E modułu wyliczającego i typ Telementu.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.

Rozmieszczenie v wewnątrz pętli while jest ważne dla sposobu przechwytywania przez jakąkolwiek anonimową funkcję 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ą, 13czyli to, f co to jest wywołanie.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ą vzmienną, przechwycona f przez w pierwszej iteracji będzie nadal przechowywać wartość 7, co 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 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 System.IDisposable do 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, e rzutowanie 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 E , jeśli 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 d lokalna 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 0 indeksu i kończąc na Length - 1indeksie.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 intelementu jestnumberswywnioskowany na wartośćthe 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ść try instrukcji wykonywanych przez interwencję.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 try kończy jeden lub więcej bloków ze skojarzonymi finally blokami, kontrola finally jest początkowo przekazywana do 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 finally końcowy bloku, sterowanie jest przekazywane finally do 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 finally momentu 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");
    }
}

bloki skojarzone z dwiema try instrukcjami są wykonywane przed przekazaniem kontroli do elementu docelowego instrukcji skoku. finallythe 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

while switch doInstrukcja kończy najbliższych otaczających, ,for,, lubforeachinstrukcji. breakThe 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 switchotaczającej, 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. for while switch foreach Jeśli instrukcja nie jest ujęta w instrukcji,, do, lub, wystąpi błąd w czasie kompilacji. breakIf a break statement is not enclosed by a switch, while, do, for, or foreach statement, a compile-time error occurs.

Gdy wiele switchinstrukcji while, do, ,for lubforeach 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.

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

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

  • finally try finally Jeśli instrukcja kończy jeden lub więcej try bloków ze skojarzonymi blokami, kontrola jest początkowo przekazywana do bloku wewnętrznej instrukcji. breakIf 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 finally końcowy bloku, sterowanie jest przekazywane finally do 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 finally momentu 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ż instrukcja bezwarunkowo transferuje kontrolę w innym miejscu, punkt break końcowy instrukcji nie jest nigdy osiągalny. breakBecause a break statement unconditionally transfers control elsewhere, the end point of a break statement is never reachable.

Instrukcja continueThe continue statement

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

continue_statement
    : 'continue' ';'
    ;

Obiekt continue docelowy instrukcji jest punktem końcowym osadzonej instrukcji najbliższej do whileotaczającej,, forlub 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. foreach for do whileJeśli instrukcja nie jest ujęta w instrukcji,,, lub, wystąpi błąd w czasie kompilacji. continueIf a continue statement is not enclosed by a while, do, for, or foreach statement, a compile-time error occurs.

Gdy wiele whileinstrukcji do, for,, foreach lub 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.

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

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

  • finally try finally Jeśli instrukcja kończy jeden lub więcej try bloków ze skojarzonymi blokami, kontrola jest początkowo przekazywana do bloku wewnętrznej instrukcji. continueIf 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 finally końcowy bloku, sterowanie jest przekazywane finally do 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 finally momentu 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ż instrukcja bezwarunkowo transferuje kontrolę w innym miejscu, punkt continue końcowy instrukcji nie jest nigdy osiągalny. continueBecause a continue statement unconditionally transfers control elsewhere, the end point of a continue statement is never reachable.

Instrukcja gotoThe goto statement

goto Instrukcja 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);
        }
    }
}

goto instrukcja 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 switch otaczającej instrukcji ( case instrukcji switch), która zawiera 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 instrukcja goto case nie jest ujęta w instrukcji switch, jeśli constant_expression nie jest niejawnie konwertowane (niejawne konwersje) do typu, najbliższej instrukcji switch lub najbliższej otaczającej Instrukcja switch nie zawiera etykiety case z podaną wartością stałą, wystąpi błąd podczas 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 switch otaczającej instrukcji ( default instrukcji switch), która zawiera 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 instrukcja nie jest ujęta switch w instrukcję lub switch Jeśli Najbliższa otaczająca instrukcja nie zawiera default etykiety, wystąpi błąd w czasie kompilacji. goto defaultIf 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.

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

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

  • finally try finally Jeśli instrukcja kończy jeden lub więcej try bloków ze skojarzonymi blokami, kontrola jest początkowo przekazywana do bloku wewnętrznej instrukcji. gotoIf 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 finally końcowy bloku, sterowanie jest przekazywane finally do 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 finally momentu 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ż instrukcja bezwarunkowo transferuje kontrolę w innym miejscu, punkt goto końcowy instrukcji nie jest nigdy osiągalny. gotoBecause a goto statement unconditionally transfers control elsewhere, the end point of a goto statement is never reachable.

Instrukcja returnThe return statement

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

return_statement
    : 'return' expression? ';'
    ;

add void set Instrukcja 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), akcesorem właściwości lub indeksatora, return metody remove dostępu do zdarzenia, Konstruktor wystąpienia, Konstruktor statyczny lub destruktor.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.

Instrukcji 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. returnA 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 finally w bloku (Instrukcja try).It is a compile-time error for a return statement to appear in a finally block (The try statement).

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

  • return Jeśli 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.
  • finally try try finally catch Jeśli instrukcja jest ujęta w jeden lub więcej lub bloków ze skojarzonymi blokami, kontrola jest początkowo przekazywana do bloku wewnętrznej instrukcji. returnIf 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 finally końcowy bloku, sterowanie jest przekazywane finally do 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 finally momentu 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ż instrukcja bezwarunkowo transferuje kontrolę w innym miejscu, punkt return końcowy instrukcji nie jest nigdy osiągalny. returnBecause a return statement unconditionally transfers control elsewhere, the end point of a return statement is never reachable.

Instrukcja throwThe throw statement

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

throw_statement
    : 'throw' expression? ';'
    ;

throw Instrukcja 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 System.Exceptionklasy w 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.

Instrukcja bez wyrażenia może być używana tylko catch w bloku, w takim przypadku instrukcja ponownie zgłasza wyjątek, który jest obecnie obsługiwany przez ten catch blok. throwA 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ż instrukcja bezwarunkowo transferuje kontrolę w innym miejscu, punkt throw końcowy instrukcji nie jest nigdy osiągalny. throwBecause 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 try otaczającej 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 punkt 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 są badane try 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:

    • try Jeśli catch catch blok otaczający punkt throw i jeśli S ma jedną klauzulę, klauzule są badane w kolejności występowania, aby znaleźć odpowiednią procedurę obsługi dla wyjątku, zgodnie z regułami określonymi w S Sekcja instrukcji try.If the try block of S encloses the throw point and if S has one or more catch clauses, the catch clauses are examined in order of appearance to locate a suitable handler for the exception, according to the rules specified in Section The try statement. 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, try Jeśli blok catch lub 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. finally Jeśli 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 finally końcowy 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

try Instrukcja 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 instrukcja umożliwia określenie bloku kodu, który jest zawsze wykonywany, gdy kontrolka try opuszcza instrukcję. tryFurthermore, 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:

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

Gdy klauzula catch 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ą jako skuteczną 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 klauzula catch określa zarówno exception_specifier z identyfikatorem, zmienna wyjątku o podanej nazwie i typie jest zadeklarowana.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 catch poza klauzulę.The exception variable corresponds to a local variable with a scope that extends over the catch clause. Podczas wykonywania exception_filter i blokuzmienna 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 bloku. catchUnless a catch clause includes an exception variable name, it is impossible to access the exception object in the filter and catch block.

Klauzula catch, która nie określa exception_specifier jest nazywana klauzulą General catch.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 C# przez kod.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 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. catchIf 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 klauzula nie określa typu ani filtru, musi być ostatnią catch klauzulą tej try instrukcji. catchIf a catch clause specifies no type and no filter, it must be the last catch clause for that try statement.

catch W bloku instrukcjathrow (Instrukcja throw) bez wyrażenia może służyć do ponownego zgłoszenia wyjątku, który został przechwycony przez blok. catchWithin 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 e zamiast ponownego zgłoszenia 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 breakczasu kompilacji dla instrukcji, continuelub 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. continue goto Gdy instrukcja finally ,, lub występuje w bloku,obiektdocelowyinstrukcjimusiznajdowaćsięwtymsamymblokulubwprzeciwnymraziewystąpibłądwczasiekompilacji.finally breakWhen 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 finally w bloku.It is a compile-time error for a return statement to occur in a finally block.

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

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

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

    • Jeśli instrukcja zawiera blok, zostaje wykonany finally blok. finally tryIf the try statement has a finally block, the finally block is executed.
    • Kontrolka jest przenoszona do punktu try końcowego 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:

    • catch Klauzule, 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. catch Jeśli 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:
      • catch Jeśli 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.
      • catch Jeśli 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 catch razie klauzulajestuważanazadopasowanie,akontrolajestprzekazywanadocatch zgodnego 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 catch końcowy bloku:When and if control reaches the end point of the catch block:
        • Jeśli instrukcja zawiera blok, zostaje wykonany finally blok. finally tryIf the try statement has a finally block, the finally block is executed.
        • Kontrolka jest przenoszona do punktu try końcowego 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 instrukcja zawiera blok, zostaje wykonany finally blok. finally tryIf 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 instrukcja nie catch ma klauzul lub jeśli żadna klauzula catch nie pasuje do wyjątku: tryIf the try statement has no catch clauses or if no catch clause matches the exception:
      • Jeśli instrukcja zawiera blok, zostaje wykonany finally blok. finally tryIf 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 try opuszcza instrukcję.The statements of a finally block are always executed when control leaves a try statement. Jest to prawdą, czy transfer kontroli odbywa się w wyniku normalnego wykonywania, w breakwyniku wykonywania continueinstrukcji,, goto, lub return try w wyniku propagowania wyjątku z Merge.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 try otaczającej 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).

Blok instrukcji jest osiągalny, try Jeśli instrukcja jest osiągalna. try tryThe try block of a try statement is reachable if the try statement is reachable.

Blok instrukcji jest osiągalny, try Jeśli instrukcja jest osiągalna. try catchA catch block of a try statement is reachable if the try statement is reachable.

Blok instrukcji jest osiągalny, try Jeśli instrukcja jest osiągalna. try finallyThe finally block of a try statement is reachable if the try statement is reachable.

Punkt try końcowy 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 try końcowy 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 się finally blok, punkt końcowy bloku jest osiągalny. finallyIf a finally block is present, the end point of the finally block is reachable.

Sprawdzone i niesprawdzone instrukcjeThe checked and unchecked statements

Instrukcje checked andunchecked 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
    ;

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

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

lock Instrukcja 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 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 (konwersje opakowania) nie jest kiedykolwiek wykonywana dla wyrażenia lock instrukcji, w rezultacie 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.

lock Instrukcja 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 obliczany 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

using Instrukcja 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 System.IDisposableimplementuje, która zawiera pojedynczą metodę bez parametrów Disposeo nazwie.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 , typ local_variable_declaration musi mieć wartość 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 forma resource_acquisition jest wyrażeniem , 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.

using Instrukcja 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 finally zawiera 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 zasób zostanie uzyskany, żadne Dispose wywołanie nie zostanie wykonane i żaden wyjątek nie jest zgłaszany. nullIf 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 myśl.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.

using Instrukcja 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 ResourceType , gdy 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();
    }
}

ResourceType Wdynamicprzeciwnym razie 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, d a 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.

using Instrukcja 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 expressionczasu kompilacji, 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 ResourceTypejako.Otherwise the interface IDisposable itself is used as the ResourceType. resource Zmienna jest niedostępna w, i niewidoczna dla osadzonej instrukcji.The resource variable is inaccessible in, and invisible to, the embedded statement.

Gdy resource_acquisition przyjmuje postać 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. using Instrukcja 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ż klasy TextReader IDisposable i implementują interfejs, przykład może używać using instrukcji, aby upewnić się, że plik źródłowy jest prawidłowo zamknięty po operacji zapisu lub odczytu. TextWriterSince the TextWriter and TextReader classes implement the IDisposable interface, the example can use using statements to ensure that the underlying file is properly closed following the write or read operations.

Instrukcja YieldThe yield statement

Instrukcja 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. yieldThe 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' ';'
    ;

yieldnie 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 yield którym 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 instrukcji yield (z jednej 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 finally w 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 try w 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 return Instrukcja 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 instrukcja znajduje się w jednym lub większej try liczbie bloków, finally skojarzone bloki nie są wykonywane w tym momencie. yield returnIf the yield return statement is within one or more try blocks, the associated finally blocks are not executed at this time.
  • Metoda obiektu Enumerator powraca true do jego obiektu wywołującego, wskazując, że obiekt Enumerator został pomyślnie zaawansowany do następnego elementu. MoveNextThe 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 MoveNext metody obiektu modułu wyliczającego 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 break Instrukcja jest wykonywana w następujący sposób:A yield break statement is executed as follows:

  • try finally finally try Jeśli instrukcja jest ujęta w jeden lub więcej bloków ze skojarzonymi blokami, kontrola jest początkowo przekazywana do bloku wewnętrznej instrukcji. yield breakIf 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 finally końcowy bloku, sterowanie jest przekazywane finally do 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 finally momentu 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 MoveNext to metoda lub Dispose metoda obiektu modułu wyliczającego.This is either the MoveNext method or Dispose method of the enumerator object.

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