陳述式Statements

C # 提供各種語句。C# provides a variety of statements. 這些語句大多對以 C 和 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 的非終端項會用於出現在其他語句中的語句。The embedded_statement nonterminal is used for statements that appear within other statements. 使用 embedded_statement 而非 語句 時,不會在這些內容中使用宣告語句和標記語句。The use of embedded_statement rather than statement excludes the use of declaration statements and labeled statements in these contexts. 範例The example

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

導致編譯時期錯誤,因為 if 語句需要 embedded_statement ,而不是其 if 分支的 語句results in a compile-time error because an if statement requires an embedded_statement rather than a statement for its if branch. 如果允許此程式碼,則會宣告變數 i ,但永遠不會使用它。If this code were permitted, then the variable i would be declared, but it could never be used. 不過請注意,藉由將宣告放 i 在區塊中,此範例會是有效的。Note, however, that by placing i's declaration in a block, the example is valid.

結束點和可執行性End points and reachability

每個語句都有一個 結束點Every statement has an end point. 以直覺來說,語句的結束點是緊接在語句後面的位置。In intuitive terms, the end point of a statement is the location that immediately follows the statement. 複合陳述式的執行規則 (包含內嵌語句的語句) 指定控制項到達內嵌語句的結束點時所採取的動作。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. 例如,當控制權到達區塊中語句的結束點時,控制權會轉移到區塊中的下一個語句。For example, when control reaches the end point of a statement in a block, control is transferred to the next statement in the block.

如果執行時可能會達到語句,則語句會被 視為 * 可 連接的 *。If a statement can possibly be reached by execution, the statement is said to be *reachable _. 相反地,如果語句不會執行,則語句會被視為 _ *無法 連線 * *。Conversely, if there is no possibility that a statement will be executed, the statement is said to be _*unreachable**.

在範例中In the example

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

無法連接的第二個調用, Console.WriteLine 因為不可能執行語句。the second invocation of Console.WriteLine is unreachable because there is no possibility that the statement will be executed.

如果編譯器判斷無法存取語句,則會回報警告。A warning is reported if the compiler determines that a statement is unreachable. 這並不是因為無法存取語句所造成的錯誤。It is specifically not an error for a statement to be unreachable.

為了判斷是否可連接特定的語句或端點,編譯器會根據針對每個語句所定義的可執行性規則來執行流程分析。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. 流程分析會將常數運算式的值納入考慮, (常數運算式) 來控制語句的行為,但不會考慮非常數運算式的可能值。The flow analysis takes into account the values of constant expressions (Constant expressions) that control the behavior of statements, but the possible values of non-constant expressions are not considered. 換句話說,基於控制流程分析的目的,會將指定類型的非常數運算式視為具有該類型的任何可能值。In 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.

在範例中In the example

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

語句的布林運算式 if 是常數運算式,因為運算子的兩個運算元 == 都是常數。the boolean expression of the if statement is a constant expression because both operands of the == operator are constants. 當常數運算式在編譯時期評估時,產生值 false Console.WriteLine 時,會將調用視為無法存取。As the constant expression is evaluated at compile-time, producing the value false, the Console.WriteLine invocation is considered unreachable. 但是,如果 i 變更為區域變數However, if i is changed to be a local variable

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

Console.WriteLine 調用會被視為可連接的,但實際上永遠不會執行。the Console.WriteLine invocation is considered reachable, even though, in reality, it will never be executed.

函式成員的 區塊 一律會被視為可到達。The block of a function member is always considered reachable. 藉由連續評估區塊中每個語句的可連線性規則,可判斷任何指定之語句的可連線性。By successively evaluating the reachability rules of each statement in a block, the reachability of any given statement can be determined.

在範例中In the example

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

第二個的 Console.WriteLine 可執行性決定如下:the reachability of the second Console.WriteLine is determined as follows:

  • 第一個 Console.WriteLine 運算式語句可連接,因為可以連接方法的區塊 FThe first Console.WriteLine expression statement is reachable because the block of the F method is reachable.
  • 第一個運算式語句的結束點是可連接的, Console.WriteLine 因為可以連線到該語句。The end point of the first Console.WriteLine expression statement is reachable because that statement is reachable.
  • 可以連線到 if 語句,因為第一個運算式語句的結束點 Console.WriteLine 是可連接的。The if statement is reachable because the end point of the first Console.WriteLine expression statement is reachable.
  • Console.WriteLine因為語句的布林運算式沒有常數值,所以可以存取第二個運算式語句 if falseThe second Console.WriteLine expression statement is reachable because the boolean expression of the if statement does not have the constant value false.

在兩種情況下,語句的結束點都可到達編譯時期錯誤:There are two situations in which it is a compile-time error for the end point of a statement to be reachable:

  • 因為 switch 語句不允許將參數區段「流經」至下一個 switch 區段,所以參數區段之語句清單的結束點會有編譯時期錯誤可供存取。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. 如果發生此錯誤,通常表示 break 缺少語句。If this error occurs, it is typically an indication that a break statement is missing.
  • 這是函數成員區塊的結束點的編譯時期錯誤,可將值計算為可連接。It is a compile-time error for the end point of the block of a function member that computes a value to be reachable. 如果發生此錯誤,通常表示 return 缺少語句。If this error occurs, it typically is an indication that a return statement is missing.

區塊Blocks

「區塊」可允許在許可單一陳述式的內容中撰寫多個陳述式。A block permits multiple statements to be written in contexts where a single statement is allowed.

block
    : '{' statement_list? '}'
    ;

區塊 是由選擇性的 statement_list (語句清單) (以大括弧括住)所組成。A block consists of an optional statement_list (Statement lists), enclosed in braces. 如果省略語句清單,則會將區塊視為空白。If the statement list is omitted, the block is said to be empty.

區塊可以包含宣告語句, (宣告 語句) 。A block may contain declaration statements (Declaration statements). 區塊中宣告的本機變數或常數範圍是區塊。The scope of a local variable or constant declared in a block is the block.

區塊的執行方式如下:A block is executed as follows:

  • 如果區塊是空的,控制權會轉移至區塊的結束點。If the block is empty, control is transferred to the end point of the block.
  • 如果區塊不是空的,就會將控制權轉移至語句清單。If the block is not empty, control is transferred to the statement list. 當和 if 控制項到達語句清單的結束點時,控制權會轉移至區塊的結束點。When and if control reaches the end point of the statement list, control is transferred to the end point of the block.

如果區塊本身可連線,就可以連線到區塊的語句清單。The statement list of a block is reachable if the block itself is reachable.

如果區塊是空的或語句清單的結束點可連線,就可以連線到區塊的結束點。The end point of a block is reachable if the block is empty or if the end point of the statement list is reachable.

包含一或多個 yield 語句 (yield 語句的區塊) 稱為 iterator 區塊。A block that contains one or more yield statements (The yield statement) is called an iterator block. 反覆運算器區塊可用來將函數成員當做反覆運算器 (反覆運算 器) 來執行。Iterator blocks are used to implement function members as iterators (Iterators). 部分額外的限制適用于 iterator 區塊:Some additional restrictions apply to iterator blocks:

  • 這是 return 語句出現在 iterator 區塊中的編譯時期錯誤 (但 yield return) 允許語句。It is a compile-time error for a return statement to appear in an iterator block (but yield return statements are permitted).
  • 反覆運算器區塊的編譯時期錯誤,包含不安全的內容 (不安全 的內容) 。It is a compile-time error for an iterator block to contain an unsafe context (Unsafe contexts). Iterator 區塊一律會定義安全內容,即使其宣告是在不安全的內容中進行嵌套也一樣。An iterator block always defines a safe context, even when its declaration is nested in an unsafe context.

語句清單Statement lists

*語句清單 _ 是由一或多個以順序撰寫的語句所組成。A *statement list _ consists of one or more statements written in sequence. 語句清單會出現在 _block * s (區塊) 和 switch_block s 中, (switch 語句) 。Statement lists occur in _block*s (Blocks) and in switch_block s (The switch statement).

statement_list
    : statement+
    ;

藉由將控制權轉移至第一個語句來執行語句清單。A statement list is executed by transferring control to the first statement. 當和 if 控制項到達語句的結束點時,控制權會轉移到下一個語句。When and if control reaches the end point of a statement, control is transferred to the next statement. 當和 if 控制項達到最後一個語句的結束點時,控制權會轉移至語句清單的結束點。When and if control reaches the end point of the last statement, control is transferred to the end point of the statement list.

如果下列至少一個條件成立,則語句清單中的語句是可連接的:A statement in a statement list is reachable if at least one of the following is true:

  • 語句是第一個語句,而語句清單本身是可連接的。The statement is the first statement and the statement list itself is reachable.
  • 可以觸達上述語句的結束點。The end point of the preceding statement is reachable.
  • 語句是標記的語句,而標籤是由可連接的 goto 語句所參考。The statement is a labeled statement and the label is referenced by a reachable goto statement.

如果清單中的最後一個語句的結束點可供存取,則語句清單的結束點是可連接的。The end point of a statement list is reachable if the end point of the last statement in the list is reachable.

空陳述式The empty statement

Empty_statement 不會執行任何動作。An empty_statement does nothing.

empty_statement
    : ';'
    ;

當需要語句的內容中沒有要執行的作業時,就會使用空的語句。An empty statement is used when there are no operations to perform in a context where a statement is required.

執行空的語句只會將控制項傳輸至語句的結束點。Execution of an empty statement simply transfers control to the end point of the statement. 因此,如果可以連接空的語句,就可以連接空語句的結束點。Thus, the end point of an empty statement is reachable if the empty statement is reachable.

使用 null 主體撰寫語句時,可以使用空的語句 whileAn empty statement can be used when writing a while statement with a null body:

bool ProcessMessage() {...}

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

此外,空的語句可以用來在區塊的結尾 "" 之前宣告標籤 }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: ;
}

標記陳述式Labeled statements

Labeled_statement 允許將語句加上標籤的前置詞。A labeled_statement permits a statement to be prefixed by a label. 區塊中允許標記的語句,但不允許做為內嵌語句。Labeled statements are permitted in blocks, but are not permitted as embedded statements.

labeled_statement
    : identifier ':' statement
    ;

加上標籤的語句會使用 識別碼 指定的名稱來宣告標籤。A labeled statement declares a label with the name given by the identifier. 標籤的範圍是宣告標籤的整個區塊,包括任何的嵌套區塊。The scope of a label is the whole block in which the label is declared, including any nested blocks. 這是具有相同名稱的兩個標籤的編譯時期錯誤,具有重迭的範圍。It is a compile-time error for two labels with the same name to have overlapping scopes.

您可以從 goto 標籤範圍內的 goto 語句 (的 語句參考標籤) 。A label can be referenced from goto statements (The goto statement) within the scope of the label. 這表示 goto 語句可以在區塊內和區塊外傳輸控制權,但永遠不會在區塊中。This means that goto statements can transfer control within blocks and out of blocks, but never into blocks.

標籤有自己的宣告空間,而且不會干擾其他識別碼。Labels have their own declaration space and do not interfere with other identifiers. 範例The example

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

有效,並使用名稱 x 做為參數和標籤。is valid and uses the name x as both a parameter and a label.

標記語句的執行會與標籤之後的語句執行完全一致。Execution of a labeled statement corresponds exactly to execution of the statement following the label.

除了正常控制流程所提供的可存取性之外,如果可連接的語句參考標籤,就可以連線到標記的語句 gotoIn 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. (例外狀況:如果 goto 語句在 try 包含區塊的內 finally ,而且標記的語句在之外,而且無法連線到 try 區塊的結束點 finally ,就無法從該語句存取標記的語句 goto 。 ) (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.)

宣告陳述式Declaration statements

Declaration_statement 宣告本機變數或常數。A declaration_statement declares a local variable or constant. 區塊中允許宣告語句,但不允許做為內嵌語句。Declaration statements are permitted in blocks, but are not permitted as embedded statements.

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

區域變數宣告Local variable declarations

Local_variable_declaration 宣告一個或多個本機變數。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_declarationlocal_variable_type 直接指定宣告所引進之變數的型別,或以識別碼表示 var 應該根據初始化運算式推斷型別。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. 型別後面接著 local_variable_declarator s 的清單,其中每個都引進一個新的變數。The type is followed by a list of local_variable_declarator s, each of which introduces a new variable. Local_variable_declarator 包含命名變數的 識別碼,並選擇性地接著 " = " token 和提供變數初始值的 local_variable_initializerA 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.

在區域變數宣告的內容中,識別碼 var 會作為內容關鍵字, (關鍵字) 。當 local_variable_type 指定為, var 而且在範圍內沒有任何名為的型別時 var ,宣告就是 隱含 型別區域變數宣告,它的型別是從關聯的初始化運算式運算式的型別推斷而來。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. 隱含型別區域變數宣告會受到下列限制:Implicitly typed local variable declarations are subject to the following restrictions:

  • Local_variable_declaration 不能包含多個 local_variable_declarator s。The local_variable_declaration cannot include multiple local_variable_declarator s.
  • Local_variable_declarator 必須包含 local_variable_initializerThe local_variable_declarator must include a local_variable_initializer.
  • Local_variable_initializer 必須是 運算式The local_variable_initializer must be an expression.
  • 初始化 運算式運算式 必須有編譯時間型別。The initializer expression must have a compile-time type.
  • 初始化 運算式運算式 無法參考宣告的變數本身The initializer expression cannot refer to the declared variable itself

以下是不正確的隱含類型區域變數宣告範例: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

本機變數的值是在使用 simple_name (簡單名稱) 的運算式中取得,而區域變數的值則是使用 指派 (指派運算子) 來修改。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). 您必須在取得值的每個位置,將區域變數明確指派 (明確 指派) 。A local variable must be definitely assigned (Definite assignment) at each location where its value is obtained.

local_variable_declaration 中宣告的區域變數範圍是宣告發生所在的區塊。The scope of a local variable declared in a local_variable_declaration is the block in which the declaration occurs. 在本機變數 local_variable_declarator 之前的文字位置中參考本機變數是錯誤的。It is an error to refer to a local variable in a textual position that precedes the local_variable_declarator of the local variable. 在本機變數的範圍內,這是編譯時期錯誤,用來宣告具有相同名稱的另一個本機變數或常數。Within the scope of a local variable, it is a compile-time error to declare another local variable or constant with the same name.

宣告多個變數的區域變數宣告相當於多個具有相同類型之單一變數的宣告。A local variable declaration that declares multiple variables is equivalent to multiple declarations of single variables with the same type. 此外,區域變數宣告中的變數初始化運算式會完全對應到緊接在宣告之後插入的指派語句。Furthermore, a variable initializer in a local variable declaration corresponds exactly to an assignment statement that is inserted immediately after the declaration.

範例The example

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

完全對應至corresponds exactly to

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

在隱含型別區域變數宣告中,所宣告的區域變數類型會與用來初始化變數的運算式型別相同。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. 例如: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>();

上述隱含類型區域變數宣告相當於下列明確的類型宣告: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>();

本機常數宣告Local constant declarations

Local_constant_declaration 宣告一個或多個本機常數。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
    ;

Local_constant_declaration 別會指定宣告所引進之常數的型別。The type of a local_constant_declaration specifies the type of the constants introduced by the declaration. 型別後面接著 constant_declarator s 的清單,其中每個都引進一個新的常數。The type is followed by a list of constant_declarator s, each of which introduces a new constant. Constant_declarator 是由命名常數的 識別碼 所組成,後面接著 " = " token,後面接著一個 constant_expression (常數運算式) ,可提供常數的值。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.

本機常數宣告的 別和 constant_expression 必須遵循與常數成員宣告的相同規則, (常數) 。The type and constant_expression of a local constant declaration must follow the same rules as those of a constant member declaration (Constants).

本機常數的值是在使用 simple_name (簡單名稱) 的運算式中取得。The value of a local constant is obtained in an expression using a simple_name (Simple names).

本機常數的範圍是發生宣告的區塊。The scope of a local constant is the block in which the declaration occurs. constant_declarator 之前的文字位置參考本機常數是錯誤的。It is an error to refer to a local constant in a textual position that precedes its constant_declarator. 在本機常數的範圍內,這是編譯時期錯誤,用來宣告具有相同名稱的另一個本機變數或常數。Within the scope of a local constant, it is a compile-time error to declare another local variable or constant with the same name.

宣告多個常數的本機常數宣告相當於多個具有相同類型之單一常數的宣告。A local constant declaration that declares multiple constants is equivalent to multiple declarations of single constants with the same type.

運算式陳述式Expression statements

Expression_statement 會評估指定的運算式。An expression_statement evaluates a given expression. 如果有的話,會捨棄運算式所計算的值(如果有的話)。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
    ;

並非所有運算式都可作為語句。Not all expressions are permitted as statements. 尤其是,和這類的運算式(例如 x + y 和) x == 1 只會計算值 (將會捨棄) ,因此不允許作為語句。In particular, expressions such as x + y and x == 1 that merely compute a value (which will be discarded), are not permitted as statements.

執行 expression_statement 會評估包含的運算式,然後將控制項傳送至 expression_statement 的結束點。Execution of an expression_statement evaluates the contained expression and then transfers control to the end point of the expression_statement. 如果可連線 expression_statementexpression_statement 的結束點。The end point of an expression_statement is reachable if that expression_statement is reachable.

選取範圍陳述式Selection statements

選取範圍語句會根據某個運算式的值,選取其中一個可能的語句來執行。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
    ;

if 陳述式The if statement

if語句會根據布林運算式的值,選取要執行的語句。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
    ;

else元件與語法所允許的述述述程式相關聯 ifAn else part is associated with the lexically nearest preceding if that is allowed by the syntax. 因此, if 表單的語句Thus, an if statement of the form

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

相當於is equivalent to

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

if語句的執行方式如下:An if statement is executed as follows:

  • 評估) 的 boolean_expression (布林運算式The boolean_expression (Boolean expressions) is evaluated.
  • 如果布林運算式產生 true ,控制權會傳送至第一個內嵌的語句。If the boolean expression yields true, control is transferred to the first embedded statement. 當和 if 控制項到達該語句的結束點時,控制權會轉移至語句的結束點 ifWhen and if control reaches the end point of that statement, control is transferred to the end point of the if statement.
  • 如果布林運算式產生, false 而且如果有某個 else 元件,則會將控制權轉移至第二個內嵌語句。If the boolean expression yields false and if an else part is present, control is transferred to the second embedded statement. 當和 if 控制項到達該語句的結束點時,控制權會轉移至語句的結束點 ifWhen and if control reaches the end point of that statement, control is transferred to the end point of the if statement.
  • 如果布林運算式產生, false 而且如果 else 元件不存在,就會將控制權轉移至語句的結束點 ifIf the boolean expression yields false and if an else part is not present, control is transferred to the end point of the if statement.

if如果可以連線到 if 語句,而且布林運算式沒有常數值,就可以連接語句的第一個內嵌語句 falseThe 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.

如果有語句可連線, if if 而且布林運算式沒有常數值,就可以連接語句的第二個內嵌語句(如果有的話) trueThe 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.

if如果至少有一個內嵌語句的結束點可連接,則語句的結束點是可連接的。The end point of an if statement is reachable if the end point of at least one of its embedded statements is reachable. 此外, if else 如果 if 可以存取語句且布林運算式沒有常數值,就可以連線到沒有部分之語句的結束點 trueIn 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.

Switch 語句The switch statement

Switch 語句會選取執行語句清單,其中有相關聯的 switch 標籤對應到 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 由關鍵字組成 switch ,後面接著一個括號運算式 (稱為 switch 運算式) ,後面接著 switch_blockA switch_statement consists of the keyword switch, followed by a parenthesized expression (called the switch expression), followed by a switch_block. Switch_block 包含零或多個 switch_section s (以大括弧括住)。The switch_block consists of zero or more switch_section s, enclosed in braces. 每個 switch_section 都包含一或多個 switch_label,後面接著 statement_list (語句清單) 。Each switch_section consists of one or more switch_label s followed by a statement_list (Statement lists).

語句的 管理類型 switch 是由 switch 運算式所建立。The governing type of a switch statement is established by the switch expression.

  • 如果 switch 運算式的類型為、、、、、、、、、、 sbyte byte short ushort int uint long ulong bool char stringenum_type,或者如果它是對應至其中一個類型的可為 null 的型別,則這是語句的控管類型 switchIf 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.
  • 否則,只有一個使用者定義的隱含轉換 (使用者定義的轉換) 必須從 switch 運算式的類型,到下列其中一個可能的控管類型:、、、、、、、、、 sbyte byte short ushort int uint long ulong char string 或,可為 null 的型別,對應到其中一個類型。Otherwise, exactly one user-defined implicit conversion (User-defined conversions) must exist from the type of the switch expression to one of the following possible governing types: sbyte, byte, short, ushort, int, uint, long, ulong, char, string, or, a nullable type corresponding to one of those types.
  • 否則,如果沒有這樣的隱含轉換,或有多個這類隱含轉換存在,就會發生編譯時期錯誤。Otherwise, if no such implicit conversion exists, or if more than one such implicit conversion exists, a compile-time error occurs.

每個標籤的常數運算式都 case 必須表示可隱含轉換的值, (隱含轉換) 至語句的管理類型 switchThe constant expression of each case label must denote a value that is implicitly convertible (Implicit conversions) to the governing type of the switch statement. 如果相同語句中的兩個或多個 case 標籤 switch 指定相同的常數值,就會發生編譯時期錯誤。A compile-time error occurs if two or more case labels in the same switch statement specify the same constant value.

Switch 語句中最多隻能有一個 default 標籤。There can be at most one default label in a switch statement.

switch語句的執行方式如下:A switch statement is executed as follows:

  • Switch 運算式會進行評估,並轉換為控管型別。The switch expression is evaluated and converted to the governing type.
  • 如果相同語句中的標籤中所指定的其中一個常數 case switch 等於 switch 運算式的值,則會將控制權轉移至相符標籤之後的語句清單 caseIf 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.
  • 如果在相同語句中的標籤中指定的常數都 case switch 不等於 switch 運算式的值,而且如果有 default 標籤,則會將控制權傳送至標籤之後的語句清單 defaultIf 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.
  • 如果相同語句中的標籤中指定的常數都 case switch 不等於 switch 運算式的值,而且如果沒有任何 default 標籤,則控制項會傳送至語句的結束點 switchIf 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.

如果可以連線到 switch 區段之語句清單的結束點,就會發生編譯時期錯誤。If the end point of the statement list of a switch section is reachable, a compile-time error occurs. 這就是所謂的「不會落在」規則中。This is known as the "no fall through" rule. 範例The example

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

有效,因為沒有切換區段具有可到達的端點。is valid because no switch section has a reachable end point. 與 C 和 c + + 不同的是,不允許執行 switch 區段至下一個 switch 區段,以及範例Unlike 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();
}

導致編譯階段錯誤。results in a compile-time error. 執行 switch 區段之後,若要接著執行另一個 switch 區段,則必須使用明確的 goto casegoto default 語句:When execution of a switch section is to be followed by execution of another switch section, an explicit goto case or goto default statement must be used:

switch (i) {
case 0:
    CaseZero();
    goto case 1;
case 1:
    CaseZeroOrOne();
    goto default;
default:
    CaseAny();
    break;
}

Switch_section 中允許有多個標籤。Multiple labels are permitted in a switch_section. 範例The example

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

有效。is valid. 此範例不會違反「無」規則,因為標籤和屬於 case 2: default: 相同 switch_section 的一部分。The example does not violate the "no fall through" rule because the labels case 2: and default: are part of the same switch_section.

當意外省略語句時,「不會」規則會防止 C 和 c + + 中發生的常見錯誤類別 breakThe "no fall through" rule prevents a common class of bugs that occur in C and C++ when break statements are accidentally omitted. 此外,由於這項規則,語句的 switch 區段 switch 可以任意重新排列,而不會影響語句的行為。In addition, because of this rule, the switch sections of a switch statement can be arbitrarily rearranged without affecting the behavior of the statement. 例如,您 switch 可以反轉上述語句的區段,而不會影響語句的行為: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;
}

Switch 區段的語句清單通常 break 會以、 goto casegoto default 語句結尾,但不允許任何呈現無法連接之語句清單的結束點的結構。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. 例如, while 已知由布林運算式控制的語句 true 永遠不會到達其結束點。For example, a while statement controlled by the boolean expression true is known to never reach its end point. 同樣地, throwreturn 語句一律會將控制項傳送到其他地方,而且永遠不會到達它的結束點。Likewise, a throw or return statement always transfers control elsewhere and never reaches its end point. 因此,下列範例是有效的:Thus, the following example is valid:

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

語句的管理類型 switch 可能是型別 stringThe governing type of a switch statement may be the type string. 例如: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;
    }
}

如同字串等號比較運算子 (字串相等運算子) , switch 語句會區分大小寫,而且只有在 switch 運算式字串完全符合 case 標籤常數時,才會執行指定的參數區段。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.

當語句的管理類型 switch 為時 string ,就可以使用此值 null 做為 case 標籤常數。When the governing type of a switch statement is string, the value null is permitted as a case label constant.

Switch_blockstatement_list 可以包含 (宣告 語句) 的宣告語句。The statement_list s of a switch_block may contain declaration statements (Declaration statements). Switch 區塊中宣告的區域變數或常數的範圍是 switch 區塊。The scope of a local variable or constant declared in a switch block is the switch block.

如果可以連線到 switch 語句,而且至少下列其中一項為真,就可以連線到指定參數區段的語句清單: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:

  • Switch 運算式是非固定值。The switch expression is a non-constant value.
  • Switch 運算式是符合 case switch 區段中之標籤的常數值。The switch expression is a constant value that matches a case label in the switch section.
  • Switch 運算式是不符合任何標籤的常數值 case ,而 switch 區段則包含 default 標籤。The switch expression is a constant value that doesn't match any case label, and the switch section contains the default label.
  • Switch 區段的 switch 標籤是由可連接的 goto case 或語句所參考 goto defaultA switch label of the switch section is referenced by a reachable goto case or goto default statement.

switch如果下列至少一個條件成立,就可以連線到語句的結束點:The end point of a switch statement is reachable if at least one of the following is true:

  • switch語句包含 break 可到達語句的可連接語句 switchThe switch statement contains a reachable break statement that exits the switch statement.
  • 可以連線到 switch 語句、switch 運算式為非常數值,且沒有任何 default 標籤。The switch statement is reachable, the switch expression is a non-constant value, and no default label is present.
  • 可以連線到 switch 語句,switch 運算式是不符合任何標籤的常數值 case ,且沒有任何 default 標籤。The switch statement is reachable, the switch expression is a constant value that doesn't match any case label, and no default label is present.

反覆運算陳述式Iteration statements

反覆運算語句會重複執行內嵌語句。Iteration statements repeatedly execute an embedded statement.

iteration_statement
    : while_statement
    | do_statement
    | for_statement
    | foreach_statement
    ;

While 語句The while statement

while語句會有條件地執行內嵌語句零次或多次。The while statement conditionally executes an embedded statement zero or more times.

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

while語句的執行方式如下:A while statement is executed as follows:

  • 評估) 的 boolean_expression (布林運算式The boolean_expression (Boolean expressions) is evaluated.
  • 如果布林運算式產生 true ,控制權會轉移至內嵌語句。If the boolean expression yields true, control is transferred to the embedded statement. 當和 if 控制項達到內嵌語句的結束點時 (可能會執行 continue 語句) ,控制權會轉移到語句的開頭 whileWhen 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.
  • 如果布林運算式產生 false ,控制權會轉移至語句的結束點 whileIf the boolean expression yields false, control is transferred to the end point of the while statement.

在語句的內嵌語句中 whilebreak (break 語句 的語句) 可用來將控制項傳送至語句的結束點 while (因此會結束內嵌語句) 的反復專案,而 continue (continue 語句 的語句) 可用來將控制項傳送至內嵌語句的結束點 (因此可執行語句) 的另一個反復專案 whileWithin 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).

while如果可以連線到 while 語句,而且布林運算式沒有常數值,就可以連接語句的內嵌語句 falseThe 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.

while如果下列至少一個條件成立,就可以連線到語句的結束點:The end point of a while statement is reachable if at least one of the following is true:

  • while語句包含 break 可到達語句的可連接語句 whileThe while statement contains a reachable break statement that exits the while statement.
  • while語句是可連接的,而且布林運算式沒有常數值 trueThe while statement is reachable and the boolean expression does not have the constant value true.

Do 語句The do statement

do語句會有條件地執行內嵌語句一或多次。The do statement conditionally executes an embedded statement one or more times.

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

do語句的執行方式如下:A do statement is executed as follows:

  • 控制權會轉移至內嵌語句。Control is transferred to the embedded statement.
  • 當和 if 控制項達到內嵌語句的結束點時 (可能 continue 會) 執行語句,則會評估 Boolean_expression (布林運算式) 。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. 如果布林運算式產生 true ,控制權會轉移至語句的開頭 doIf the boolean expression yields true, control is transferred to the beginning of the do statement. 否則,控制權會轉移至語句的結束點 doOtherwise, control is transferred to the end point of the do statement.

在語句的內嵌語句中 dobreak Break 語句 (的 語句) 可用來將控制項傳送至語句的結束點 do (因此會結束內嵌語句) 的反復專案,以及 continue (continue 語句) 可用來將控制項傳送至內嵌語句的結束點。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.

do如果可以連線到語句,就可以連線到語句的內嵌語句 doThe embedded statement of a do statement is reachable if the do statement is reachable.

do如果下列至少一個條件成立,就可以連線到語句的結束點:The end point of a do statement is reachable if at least one of the following is true:

  • do語句包含 break 可到達語句的可連接語句 doThe do statement contains a reachable break statement that exits the do statement.
  • 內嵌語句的結束點是可存取的,而且布林運算式沒有常數值 trueThe end point of the embedded statement is reachable and the boolean expression does not have the constant value true.

For 語句The for statement

for語句會評估一系列的初始化運算式,然後在條件為 true 時,重複執行內嵌的語句,並評估反覆運算運算式的順序。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(如果有的話)是由 local_variable_declaration (區域變數宣告) 或 statement_expression (運算式語句清單) 以逗號分隔。The for_initializer, if present, consists of either a local_variable_declaration (Local variable declarations) or a list of statement_expression s (Expression statements) separated by commas. For_initializer 所宣告的區域變數範圍是從變數的 local_variable_declarator 開始,並延伸至內嵌語句的結尾。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. 範圍包含 for_conditionfor_iteratorThe scope includes the for_condition and the for_iterator.

For_condition(如果有的話)必須是 boolean_expression (布林運算式) 。The for_condition, if present, must be a boolean_expression (Boolean expressions).

For_iterator(如果有的話)是由 Statement_expression s (運算式語句的清單所組成) 以逗號分隔。The for_iterator, if present, consists of a list of statement_expression s (Expression statements) separated by commas.

For 語句的執行方式如下:A for statement is executed as follows:

  • 如果有 for_initializer ,則變數初始化運算式或語句運算式會依照其撰寫的順序來執行。If a for_initializer is present, the variable initializers or statement expressions are executed in the order they are written. 此步驟只會執行一次。This step is only performed once.
  • 如果有 for_condition ,則會進行評估。If a for_condition is present, it is evaluated.
  • 如果 for_condition 不存在或評估產生 true ,控制權會轉移至內嵌語句。If the for_condition is not present or if the evaluation yields true, control is transferred to the embedded statement. 當和 When 控制項達到內嵌語句的結束點時 (可能從語句) 執行時 continuefor_iterator 的運算式(如果有的話)會依序進行評估,然後再執行另一個反復專案,從上述步驟中的 for_condition 評估開始。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.
  • 如果 for_condition 存在且評估結果產生 false ,控制權會轉移至語句的結束點 forIf the for_condition is present and the evaluation yields false, control is transferred to the end point of the for statement.

在語句的內嵌語句中 forbreak 語句 (break 語句) 可用來將控制項傳送至語句的結束點 for (因此會結束內嵌語句) 的反復專案,而 continue (continue 語句 的語句) 可用來將控制項傳送至內嵌語句的結束點 (然後執行 for_iterator ,然後執行語句的另一個反覆運算 for ,從 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).

for如果下列其中一個條件成立,就可以連線到語句的內嵌語句:The embedded statement of a for statement is reachable if one of the following is true:

  • for語句可連線,而且沒有 for_condition 存在。The for statement is reachable and no for_condition is present.
  • for語句可連線,而且有 for_condition 存在,而且沒有常數值 falseThe for statement is reachable and a for_condition is present and does not have the constant value false.

for如果下列至少一個條件成立,就可以連線到語句的結束點:The end point of a for statement is reachable if at least one of the following is true:

  • for語句包含 break 可到達語句的可連接語句 forThe for statement contains a reachable break statement that exits the for statement.
  • for語句可連線,而且有 for_condition 存在,而且沒有常數值 trueThe for statement is reachable and a for_condition is present and does not have the constant value true.

Foreach 語句The foreach statement

foreach語句會列舉集合的元素,並針對集合的每個元素執行內嵌語句。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
    ;

語句的 類型識別碼 會宣告 foreach 語句的 *反覆運算變數 _。The type and identifier of a foreach statement declare the *iteration variable _ of the statement. 如果將 var 識別碼指定為 _local_variable_type *,而且在範圍內沒有任何名為的型別 var ,則反覆運算變數會被視為 隱含類型的反覆運算變數,而其型別會被視為語句的元素類型 foreach ,如下所示。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. 反覆運算變數會對應至範圍延伸至內嵌語句的唯讀區域變數。The iteration variable corresponds to a read-only local variable with a scope that extends over the embedded statement. 在語句執行期間 foreach ,反覆運算變數表示目前正在執行反覆運算的集合元素。During execution of a foreach statement, the iteration variable represents the collection element for which an iteration is currently being performed. 如果內嵌語句嘗試透過指派或和) 運算子來修改反覆運算變數 (, ++ -- 或將反覆運算變數作為或參數來傳遞,就會發生編譯時期 ref 錯誤 outA 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.

在下列中,為了簡潔起見, IEnumerableIEnumerator 和會 IEnumerable<T> IEnumerator<T> 參考命名空間和中的對應 System.Collections 類型 System.Collections.GenericIn 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.

Foreach 語句的編譯時期處理會先判斷運算式的 集合類型 _、 _列舉數值型別*_ 和 _ *元素類型**。The compile-time processing of a foreach statement first determines the collection type _, _enumerator type_ and _ element type of the expression. 這項決定會繼續進行,如下所示:This determination proceeds as follows:

  • 如果運算式的型別 X 是陣列型別,則會有從介面 (的隱含參考轉換, X IEnumerable 因為 System.Array 它會) 執行這個介面。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). 集合類型 _ 是 IEnumerable 介面, _列舉值型_ 別是介面, IEnumerator 而 _ 元素類型 是陣列類型的元素類型 XThe 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 類型為,則 dynamic 會從 運算式 隱含轉換成 IEnumerable 介面 (隱含動態轉換) 。If the type X of expression is dynamic then there is an implicit conversion from expression to the IEnumerable interface (Implicit dynamic conversions). 集合類型 _ 是 IEnumerable 介面,而列舉值 _*_ 別為 IEnumerator 介面。The collection type _ is the IEnumerable interface and the _enumerator type*_ is the IEnumerator interface. 如果將 var 識別碼指定為 _local_variable_type *,則 元素類型dynamic ,否則為 objectIf the var identifier is given as the _local_variable_type* then the element type is dynamic, otherwise it is object.

  • 否則,請判斷型別是否 X 具有適當的 GetEnumerator 方法:Otherwise, determine whether the type X has an appropriate GetEnumerator method:

    • X 具有識別碼 GetEnumerator 和無類型引數的類型上執行成員查閱。Perform member lookup on the type X with identifier GetEnumerator and no type arguments. 如果成員查閱未產生相符的結果,或是產生不明確的結果,或產生不是方法群組的比對,請檢查是否有可列舉的介面,如下所述。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. 如果成員查閱產生方法群組以外的任何結果,或沒有相符項,建議您發出警告。It is recommended that a warning be issued if member lookup produces anything except a method group or no match.
    • 使用產生的方法群組和空的引數清單,執行多載解析。Perform overload resolution using the resulting method group and an empty argument list. 如果多載解析不會產生任何適用的方法、產生不明確的結果,或是產生單一最佳方法,但是該方法不是靜態或非公用的,請檢查是否有可列舉的介面,如下所述。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. 如果多載解析產生了明確的公用實例方法,或沒有適用的方法,建議您發出警告。It is recommended that a warning be issued if overload resolution produces anything except an unambiguous public instance method or no applicable methods.
    • 如果方法的傳回型別 E GetEnumerator 不是類別、結構或介面型別,就會產生錯誤,而且不會採取進一步的步驟。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.
    • 成員查閱是 E 以識別碼 Current 和沒有類型引數來執行。Member lookup is performed on E with the identifier Current and no type arguments. 如果成員查閱未產生相符的結果,結果會是錯誤,或者結果會是除了允許讀取的公用實例屬性以外的任何內容,會產生錯誤,而且不會採取進一步的步驟。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.
    • 成員查閱是 E 以識別碼 MoveNext 和沒有類型引數來執行。Member lookup is performed on E with the identifier MoveNext and no type arguments. 如果成員查閱未產生相符的結果,結果會是錯誤,或是除了方法群組以外的結果以外,會產生錯誤,而且不會採取進一步的步驟。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.
    • 多載解析會在具有空白引數清單的方法群組上執行。Overload resolution is performed on the method group with an empty argument list. 如果多載解析結果不會產生任何適用的方法、產生不明確的結果,或是產生單一最佳方法,但是該方法不是靜態或非公用,或其傳回類型不是 bool ,則會產生錯誤,而且不會採取進一步的步驟。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.
    • 集合型 別是 X ,列舉值 __ 別是 E ,而 _ 元素 type 是屬性的型別 CurrentThe collection type _ is X, the _enumerator type_ is E, and the _ element type is the type of the Current property.
  • 否則,請檢查是否有可列舉的介面:Otherwise, check for an enumerable interface:

    • 如果您在的所有類型中 Ti 都有隱含的轉換,則會 X IEnumerable<Ti> 有唯一的型別,而不是,另一個則是 T T dynamic Ti 從到的隱含轉換, IEnumerable<T>IEnumerable<Ti> collection type _ 是介面 IEnumerable<T> , _列舉值型_ 別是介面 IEnumerator<T> ,而 _ 元素類型TIf 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.
    • 否則,如果有多個這種類型 T ,則會產生錯誤,而且不會採取進一步的步驟。Otherwise, if there is more than one such type T, then an error is produced and no further steps are taken.
    • 否則,如果從介面隱含轉換,則 X System.Collections.IEnumerable 集合類型 _ 是這個介面, _列舉值型_ 別是介面 System.Collections.IEnumerator ,而 _ 元素類型objectOtherwise, 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.
    • 否則會產生錯誤,而且不會採取進一步的步驟。Otherwise, an error is produced and no further steps are taken.

上述步驟如果成功,就會明確地產生集合類型 C 、列舉值型別 E 和元素類型 TThe above steps, if successful, unambiguously produce a collection type C, enumerator type E and element type T. 表單的 foreach 語句A foreach statement of the form

foreach (V v in x) embedded_statement

接著會展開為:is then expanded to:

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

e運算式 x 或內嵌的語句或程式的任何其他原始程式碼都看不到或無法存取變數。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. v 內嵌語句中,變數是唯讀的。The variable v is read-only in the embedded statement. 如果沒有明確的轉換 (明確 的轉換) 從 T (元素類型) V (foreach 語句 local_variable_type 中的 ) ,就會產生錯誤,而且不會採取進一步的步驟。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. 如果 x 有值 nullSystem.NullReferenceException 則會在執行時間擲回。If x has the value null, a System.NullReferenceException is thrown at run-time.

您可以使用實值以不同的方式來執行指定的 foreach 語句,例如基於效能考慮,只要行為與上述擴充一致即可。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.

vWhile 迴圈內的位置對於 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.

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

如果 v 是在 while 迴圈之外宣告,則會在所有反復專案之間共用,而且在 for 迴圈之後的值會是最後一個值,也 13 就是要列印的調用 fIf 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. 相反地,因為每個反復專案都有自己的變數 v ,所以 f 在第一個反復專案中所捕捉的變數將會繼續保留值 7 ,也就是將列印的內容。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. (注意:舊版的 c # 會在 v while 迴圈之外宣告。 ) (Note: earlier versions of C# declared v outside of the while loop.)

Finally 區塊的主體會根據下列步驟來進行:The body of the finally block is constructed according to the following steps:

  • 如果從介面隱含轉換 E System.IDisposable ,則If there is an implicit conversion from E to the System.IDisposable interface, then

    • 如果 E 是不可為 null 的實值型別,則 finally 子句會展開為對等的語義:If E is a non-nullable value type then the finally clause is expanded to the semantic equivalent of:

      finally {
          ((System.IDisposable)e).Dispose();
      }
      
    • 否則,finally 子句會展開為對等的語義:Otherwise the finally clause is expanded to the semantic equivalent of:

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

    但是,如果 E 是實值型別,或是具現化為實值型別的型別參數,則的轉換 e System.IDisposable 將不會造成進行的裝箱。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.

  • 否則,如果 E 是密封型別,finally 子句會展開為空的區塊:Otherwise, if E is a sealed type, the finally clause is expanded to an empty block:

    finally {
    }
    
  • 否則,finally 子句會展開為:Otherwise, the finally clause is expanded to:

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

    d任何使用者程式碼都看不到或無法存取本機變數。The local variable d is not visible to or accessible to any user code. 尤其是,它不會與範圍包含 finally 區塊的任何其他變數發生衝突。In particular, it does not conflict with any other variable whose scope includes the finally block.

foreach遍歷陣列元素的順序如下:針對單一維度的陣列元素會以遞增的索引順序來進行,並從索引開始,  0 並以索引結尾 Length - 1The 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. 若為多維度陣列,則會遍歷元素,以便先增加最右邊維度的索引,然後再增加下一個左邊的維度,依此類推。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.

下列範例會依元素順序列印二維陣列中的每個值: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();
    }
}

產生的輸出如下所示:The output produced is as follows:

1.2 2.3 3.4 4.5 5.6 6.7 7.8 8.9

在範例中In the example

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

的型別 n 推斷為的 int 元素型別 numbersthe type of n is inferred to be int, the element type of numbers.

跳躍陳述式Jump statements

跳躍語句無條件地傳輸控制權。Jump statements unconditionally transfer control.

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

跳躍語句傳輸控制權的位置稱為跳躍語句的 目標The location to which a jump statement transfers control is called the target of the jump statement.

當跳躍語句出現在區塊中,而且該跳躍語句的目標在該區塊之外時,即表示跳過語句結束區塊 。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. 雖然跳躍語句可能會將控制權轉移到區塊,但永遠不會將控制項傳送至區塊。While a jump statement may transfer control out of a block, it can never transfer control into a block.

執行跳躍語句會因為中間語句的存在而複雜 tryExecution of jump statements is complicated by the presence of intervening try statements. 如果沒有這類 try 語句,跳躍語句會無條件地將控制權從跳躍語句傳送至其目標。In the absence of such try statements, a jump statement unconditionally transfers control from the jump statement to its target. 如果存在這類仲介 try 語句,執行會更複雜。In the presence of such intervening try statements, execution is more complex. 如果跳躍陳述式結束一個或多個 try 具有相關聯區塊的區塊 finally ,則會一開始就將控制權轉移到 finally 最內層的 try 語句區塊。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. 當和 if 控制項到達區塊的結束點時 finally ,控制權會轉移到 finally 下一個封入語句的區塊 tryWhen and if control reaches the end point of a finally block, control is transferred to the finally block of the next enclosing try statement. 此程式會重複執行,直到 finally 所有中間語句的區塊 try 都已執行為止。This process is repeated until the finally blocks of all intervening try statements have been executed.

在範例中In 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");
    }
}

finally與兩個語句相關聯的區塊 try 會在控制傳送至跳躍語句的目標之前執行。the finally blocks associated with two try statements are executed before control is transferred to the target of the jump statement.

產生的輸出如下所示:The output produced is as follows:

Before break
Innermost finally block
Outermost finally block
After break

Break 語句The break statement

語句會結束 break 最接近的封閉、、、 switch while do forforeach 語句。The break statement exits the nearest enclosing switch, while, do, for, or foreach statement.

break_statement
    : 'break' ';'
    ;

語句的目標 break 是最接近的封閉、、、 switch while do forforeach 語句的結束點。The target of a break statement is the end point of the nearest enclosing switch, while, do, for, or foreach statement. 如果語句未以 break switchwhiledo 、或語句括住 for foreach ,就會發生編譯時期錯誤。If a break statement is not enclosed by a switch, while, do, for, or foreach statement, a compile-time error occurs.

當多個、、、或語句在彼此之間 switch while do for foreach 進行嵌套時, break 語句只適用于最內層的語句。When multiple switch, while, do, for, or foreach statements are nested within each other, a break statement applies only to the innermost statement. 若要在多個嵌套層級之間傳輸控制權, goto 必須使用 goto 語句 (語句) 。To transfer control across multiple nesting levels, a goto statement (The goto statement) must be used.

break語句無法 finally (try 語句) 結束區塊。A break statement cannot exit a finally block (The try statement). break 語句在區塊中發生時 finally ,語句的目標 break 必須在同一個區塊內 finally ; 否則,就會發生編譯時期錯誤。When a break statement occurs within a finally block, the target of the break statement must be within the same finally block; otherwise, a compile-time error occurs.

break語句的執行方式如下:A break statement is executed as follows:

  • 如果 break 語句結束一個或多個 try 具有相關聯 finally 區塊的區塊,則會一開始就將控制權轉移到 finally 最內層的 try 語句區塊。If the break statement exits one or more try blocks with associated finally blocks, control is initially transferred to the finally block of the innermost try statement. 當和 if 控制項到達區塊的結束點時 finally ,控制權會轉移到 finally 下一個封入語句的區塊 tryWhen and if control reaches the end point of a finally block, control is transferred to the finally block of the next enclosing try statement. 此程式會重複執行,直到 finally 所有中間語句的區塊 try 都已執行為止。This process is repeated until the finally blocks of all intervening try statements have been executed.
  • 控制權會轉移至語句的目標 breakControl is transferred to the target of the break statement.

因為 break 語句會無條件地將控制權傳送到其他地方,所以 break 永遠不會到達語句的結束點。Because a break statement unconditionally transfers control elsewhere, the end point of a break statement is never reachable.

Continue 語句The continue statement

continue語句會啟動最接近的封入 whiledoforforeach 語句的新反復專案。The continue statement starts a new iteration of the nearest enclosing while, do, for, or foreach statement.

continue_statement
    : 'continue' ';'
    ;

語句的目標 continue 是最接近的封入 whiledoforforeach 語句之內嵌語句的結束點。The target of a continue statement is the end point of the embedded statement of the nearest enclosing while, do, for, or foreach statement. 如果語句未以 continue whiledo 、或語句括住 for foreach ,就會發生編譯時期錯誤。If a continue statement is not enclosed by a while, do, for, or foreach statement, a compile-time error occurs.

當多個、、或語句在彼此之間 while do for foreach 進行嵌套時, continue 語句只適用于最內層的語句。When multiple while, do, for, or foreach statements are nested within each other, a continue statement applies only to the innermost statement. 若要在多個嵌套層級之間傳輸控制權, goto 必須使用 goto 語句 (語句) 。To transfer control across multiple nesting levels, a goto statement (The goto statement) must be used.

continue語句無法 finally (try 語句) 結束區塊。A continue statement cannot exit a finally block (The try statement). continue 語句在區塊中發生時 finally ,語句的目標 continue 必須在同一個區塊內 finally ; 否則會發生編譯時期錯誤。When a continue statement occurs within a finally block, the target of the continue statement must be within the same finally block; otherwise a compile-time error occurs.

continue語句的執行方式如下:A continue statement is executed as follows:

  • 如果 continue 語句結束一個或多個 try 具有相關聯 finally 區塊的區塊,則會一開始就將控制權轉移到 finally 最內層的 try 語句區塊。If the continue statement exits one or more try blocks with associated finally blocks, control is initially transferred to the finally block of the innermost try statement. 當和 if 控制項到達區塊的結束點時 finally ,控制權會轉移到 finally 下一個封入語句的區塊 tryWhen and if control reaches the end point of a finally block, control is transferred to the finally block of the next enclosing try statement. 此程式會重複執行,直到 finally 所有中間語句的區塊 try 都已執行為止。This process is repeated until the finally blocks of all intervening try statements have been executed.
  • 控制權會轉移至語句的目標 continueControl is transferred to the target of the continue statement.

因為 continue 語句會無條件地將控制權傳送到其他地方,所以 continue 永遠不會到達語句的結束點。Because a continue statement unconditionally transfers control elsewhere, the end point of a continue statement is never reachable.

goto 陳述式The goto statement

goto語句會將控制項傳送至由標籤標記的語句。The goto statement transfers control to a statement that is marked by a label.

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

goto Identifier 語句的目標是具有指定標籤的標記語句。The target of a goto identifier statement is the labeled statement with the given label. 如果目前的函式成員中沒有具有指定名稱的標籤,或者如果語句不在 goto 標籤的範圍內,就會發生編譯時期錯誤。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. 這項規則允許使用語句,將 goto 控制項從嵌套範圍中傳送,但不允許轉換成嵌套的範圍。This rule permits the use of a goto statement to transfer control out of a nested scope, but not into a nested scope. 在範例中In 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語句是用來將控制項從嵌套範圍中轉移。a goto statement is used to transfer control out of a nested scope.

語句的目標 goto case 是緊接在 switch switch 語句) (switch 語句 的語句清單,其中包含 case 具有指定常數值的標籤。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. 如果語句未以 goto case 語句括住 switch ,則如果 constant_expression 無法隱含轉換 (隱含轉換) 至最接近的封入語句的管理型別 switch ,或如果最接近的封入 switch 語句沒有包含 case 具有指定常數值的標籤,就會發生編譯時期錯誤。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.

語句的目標 goto default 是直接封入語句中的語句清單 switch , (switch 語句) ,其中包含 default 標籤。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. 如果 goto default 語句未以語句括住 switch ,或最接近的封入 switch 語句未包含 default 標籤,就會發生編譯時期錯誤。If the goto default statement is not enclosed by a switch statement, or if the nearest enclosing switch statement does not contain a default label, a compile-time error occurs.

goto語句無法 finally (try 語句) 結束區塊。A goto statement cannot exit a finally block (The try statement). goto 語句在區塊中發生時 finally ,語句的目標 goto 必須在同一個區塊內 finally ,否則就會發生編譯時期錯誤。When a goto statement occurs within a finally block, the target of the goto statement must be within the same finally block, or otherwise a compile-time error occurs.

goto語句的執行方式如下:A goto statement is executed as follows:

  • 如果 goto 語句結束一個或多個 try 具有相關聯 finally 區塊的區塊,則會一開始就將控制權轉移到 finally 最內層的 try 語句區塊。If the goto statement exits one or more try blocks with associated finally blocks, control is initially transferred to the finally block of the innermost try statement. 當和 if 控制項到達區塊的結束點時 finally ,控制權會轉移到 finally 下一個封入語句的區塊 tryWhen and if control reaches the end point of a finally block, control is transferred to the finally block of the next enclosing try statement. 此程式會重複執行,直到 finally 所有中間語句的區塊 try 都已執行為止。This process is repeated until the finally blocks of all intervening try statements have been executed.
  • 控制權會轉移至語句的目標 gotoControl is transferred to the target of the goto statement.

因為 goto 語句會無條件地將控制權傳送到其他地方,所以 goto 永遠不會到達語句的結束點。Because a goto statement unconditionally transfers control elsewhere, the end point of a goto statement is never reachable.

Return 語句The return statement

return語句會將控制權傳回給出現語句的函式目前的呼叫端 returnThe return statement returns control to the current caller of the function in which the return statement appears.

return_statement
    : 'return' expression? ';'
    ;

return沒有運算式的語句只能用於未計算值的函式成員,也就是具有結果型別 (方法主體) 的方法 voidset 屬性或索引子的存取子、事件的存取子、 add remove 實例的函式、靜態的函式,或析構函數。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.

return具有運算式的語句只能用在計算值的函式成員,也就是具有非 void 結果型別的方法、 get 屬性或索引子的存取子,或是使用者定義的運算子。A return statement with an expression can only be used in a function member that computes a value, that is, a method with a non-void result type, the get accessor of a property or indexer, or a user-defined operator. 隱含轉換 (隱含 轉換) 必須存在於運算式的型別和包含函數成員的傳回型別。An implicit conversion (Implicit conversions) must exist from the type of the expression to the return type of the containing function member.

您也可以在匿名函式運算式的主體中使用 Return 語句) (匿名函式 運算式 ,並參與判斷這些函數有哪些轉換存在。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.

這是編譯時期錯誤, return 語句會出現在 finally try 語句) (的區塊中。It is a compile-time error for a return statement to appear in a finally block (The try statement).

return語句的執行方式如下:A return statement is executed as follows:

  • 如果 return 語句指定運算式,則會評估運算式,並透過隱含轉換將產生的值轉換成包含函式的傳回型別。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. 轉換的結果會成為函數所產生的結果值。The result of the conversion becomes the result value produced by the function.
  • 如果 return 語句是以一或多個 trycatch 具有相關聯區塊的區塊括住 finally ,則會一開始就將控制權轉移到 finally 最內層的 try 語句區塊。If the return statement is enclosed by one or more try or catch blocks with associated finally blocks, control is initially transferred to the finally block of the innermost try statement. 當和 if 控制項到達區塊的結束點時 finally ,控制權會轉移到 finally 下一個封入語句的區塊 tryWhen and if control reaches the end point of a finally block, control is transferred to the finally block of the next enclosing try statement. 此程式會重複執行,直到 finally 所有封閉語句的區塊 try 都已執行為止。This process is repeated until the finally blocks of all enclosing try statements have been executed.
  • 如果包含的函式不是非同步函式,則會將控制權傳回給包含函式的呼叫端,以及結果值(如果有的話)。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.
  • 如果包含函式是非同步函式,則會將控制權傳回給目前的呼叫端,而結果值(如果有的話)會記錄在傳回工作中,如 (列舉值介面) 中所述。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).

因為 return 語句會無條件地將控制權傳送到其他地方,所以 return 永遠不會到達語句的結束點。Because a return statement unconditionally transfers control elsewhere, the end point of a return statement is never reachable.

Throw 語句The throw statement

throw 陳述式會擲回例外狀況。The throw statement throws an exception.

throw_statement
    : 'throw' expression? ';'
    ;

具有運算式的語句會擲回 throw 評估運算式所產生的值。A throw statement with an expression throws the value produced by evaluating the expression. 運算式必須表示類別類型的值,該類別類型 System.Exception 衍生自 System.Exception 或具有 (的類型參數類型, System.Exception 或) 為其有效基類的子類別。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. 如果運算式的評估產生 nullSystem.NullReferenceException 則會改為擲回。If evaluation of the expression produces null, a System.NullReferenceException is thrown instead.

throw沒有運算式的語句只能用在 catch 區塊中,在這種情況下,語句會重新擲回目前由該區塊處理的例外狀況 catchA 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.

因為 throw 語句會無條件地將控制權傳送到其他地方,所以 throw 永遠不會到達語句的結束點。Because a throw statement unconditionally transfers control elsewhere, the end point of a throw statement is never reachable.

當擲回例外狀況時,控制權會轉移到 catch 可處理例外狀況之封閉式語句中的第一個子句 tryWhen an exception is thrown, control is transferred to the first catch clause in an enclosing try statement that can handle the exception. 從例外狀況的點到將控制項傳送至適當的例外狀況處理常式時,所發生的進程稱為「例外狀況傳播 _」。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 . 例外狀況的傳播包括重複評估下列步驟,直到 catch 找到符合例外狀況的子句為止。Propagation of an exception consists of repeatedly evaluating the following steps until a catch clause that matches the exception is found. 在此描述中, 擲回點* 最初是擲回例外狀況的位置。In this description, the _ throw point* is initially the location at which the exception is thrown.

  • 在目前的函式成員中, try 會檢查包圍擲點的每個語句。In the current function member, each try statement that encloses the throw point is examined. 針對每個語句 S ,從最內層的語句開始, try 並以最外層的 try 語句結束,將會評估下列步驟:For each statement S, starting with the innermost try statement and ending with the outermost try statement, the following steps are evaluated:

    • 如果 try 的區塊 S 包含了擲回點,而且如果有一個或多個 catch 子句,則 catch 會根據 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. 如果找到相符的 catch 子句,則會將控制項傳送至該子句的區塊,以完成例外狀況傳播 catchIf a matching catch clause is located, the exception propagation is completed by transferring control to the block of that catch clause.

    • 否則,如果 try 區塊或 catch 區塊 S 封閉了擲回點,而且如果 Sfinally 區塊,就會將控制權轉移至 finally 區塊。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 另一個例外狀況,則會終止處理目前的例外狀況。If the finally block throws another exception, processing of the current exception is terminated. 否則,當控制權到達區塊的結束點時 finally ,就會繼續處理目前的例外狀況。Otherwise, when control reaches the end point of the finally block, processing of the current exception is continued.

  • 如果例外狀況處理常式不在目前的函式調用中,就會終止函式呼叫,併發生下列其中一種情況:If an exception handler was not located in the current function invocation, the function invocation is terminated, and one of the following occurs:

    • 如果目前的函式是非非同步,則會為函式的呼叫者重複上述步驟,並將擲回點對應至叫用函式成員的語句。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.

    • 如果目前的函式是非同步和工作傳回,則會將例外狀況記錄在傳回工作中,該工作會在 [列舉值] 介面中所述的錯誤或已取消狀態下出現。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.

    • 如果目前的函式是非同步和傳回 void,則會通知目前線程的同步處理內容,如可列舉 介面中所述。If the current function is async and void-returning, the synchronization context of the current thread is notified as described in Enumerable interfaces.

  • 如果例外狀況處理終止目前線程中的所有函數成員調用,表示執行緒沒有例外狀況的處理常式,則執行緒本身就會終止。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. 這種終止的影響是實作為定義。The impact of such termination is implementation-defined.

Try 語句The try statement

try語句會提供一種機制來攔截執行區塊時所發生的例外狀況。The try statement provides a mechanism for catching exceptions that occur during execution of a block. 此外, try 語句還能指定控制項離開語句時一律執行的程式碼區塊 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
    ;

有三種可能的 try 語句形式:There are three possible forms of try statements:

  • try後面接著一個或多個區塊的區塊 catchA try block followed by one or more catch blocks.
  • try後面接著區塊的區塊 finallyA try block followed by a finally block.
  • 後面接著一個或多個區塊,後面接著一個 try 區塊的區塊 catch finallyA try block followed by one or more catch blocks followed by a finally block.

catch 子句指定 exception_specifier 時,型別必須是 System.Exception 、衍生自的型別, System.Exception 或是具有 (的型別參數型別, System.Exception 或) 為其有效基類的子類別。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.

catch 子句同時指定具有 識別碼exception_specifier 時,會宣告指定名稱和類型的 *exception 變數 _。When a catch clause specifies both an exception_specifier with an identifier, an *exception variable _ of the given name and type is declared. 例外狀況變數對應至區域變數,其範圍會延伸至 catch 子句。The exception variable corresponds to a local variable with a scope that extends over the catch clause. 在 _exception_filter * 和 區塊 的執行期間,例外狀況變數代表目前正在處理的例外狀況。During execution of the _exception_filter* and block, the exception variable represents the exception currently being handled. 基於明確指派檢查的目的,會將例外狀況變數視為其整個範圍中的明確指派。For purposes of definite assignment checking, the exception variable is considered definitely assigned in its entire scope.

除非 catch 子句包含例外狀況變數名稱,否則無法存取篩選和區塊中的例外狀況物件 catchUnless a catch clause includes an exception variable name, it is impossible to access the exception object in the filter and catch block.

catch未指定 exception_specifier 的子句稱為一般 catch 子句。A catch clause that does not specify an exception_specifier is called a general catch clause.

某些程式設計語言可能會支援無法表示為衍生自之物件的例外狀況 System.Exception ,但 c # 程式碼永遠無法產生這類例外狀況。Some programming languages may support exceptions that are not representable as an object derived from System.Exception, although such exceptions could never be generated by C# code. 一般 catch 子句可用來攔截這類例外狀況。A general catch clause may be used to catch such exceptions. 因此,一般 catch 子句在語義上不同于指定類型的 System.Exception ,前者可能也會攔截其他語言的例外狀況。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.

為了找出例外狀況的處理常式, catch 子句會以詞法順序進行檢查。In order to locate a handler for an exception, catch clauses are examined in lexical order. 如果 catch 子句指定了型別,但是沒有例外狀況篩選準則,則在相同語句中,後面的子句會有編譯時期錯誤, catch try 以指定與該類型相同或衍生自的類型。If a catch clause specifies a type but no exception filter, it is a compile-time error for a later catch clause in the same try statement to specify a type that is the same as, or is derived from, that type. 如果 catch 子句未指定任何類型,而且沒有篩選,則它必須是 catch 該語句的最後一個子句 tryIf a catch clause specifies no type and no filter, it must be the last catch clause for that try statement.

catch 區塊中, throw (throw 語句 的語句) 不含運算式的語句可以用來重新擲回區塊攔截到的例外狀況 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. 例外狀況變數的指派不會改變重新擲回的例外狀況。Assignments to an exception variable do not alter the exception that is re-thrown.

在範例中In 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);
        }
    }
}

方法會攔截 F 例外狀況、將某些診斷資訊寫入主控台、變更例外狀況變數,然後重新擲回例外狀況。the method F catches an exception, writes some diagnostic information to the console, alters the exception variable, and re-throws the exception. 重新擲回的例外狀況是原始的例外狀況,因此產生的輸出為:The exception that is re-thrown is the original exception, so the output produced is:

Exception in F: G
Exception in Main: G

如果擲回第一個 catch 區塊 e ,而不是重新擲回目前的例外狀況,則產生的輸出會如下所示: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

它是、或語句的編譯時期錯誤 breakcontinue goto 可將控制項從區塊中傳輸 finallyIt is a compile-time error for a break, continue, or goto statement to transfer control out of a finally block. breakcontinuegoto 語句發生在區塊中時 finally ,語句的目標必須在同一個 finally 區塊內,否則就會發生編譯時期錯誤。When a break, continue, or goto statement occurs in a finally block, the target of the statement must be within the same finally block, or otherwise a compile-time error occurs.

這是 return 語句在區塊中發生的編譯時期錯誤 finallyIt is a compile-time error for a return statement to occur in a finally block.

try語句的執行方式如下:A try statement is executed as follows:

  • 控制權會轉移至 try 區塊。Control is transferred to the try block.

  • 當和 if 控制項到達區塊的結束點時 tryWhen and if control reaches the end point of the try block:

    • 如果 try 語句具有 finally 區塊,則 finally 會執行區塊。If the try statement has a finally block, the finally block is executed.
    • 控制權會傳送至語句的結束點 tryControl is transferred to the end point of the try statement.
  • 如果在執行區塊時,將例外狀況傳播至 try 語句 tryIf an exception is propagated to the try statement during execution of the try block:

    • catch檢查子句(如果有的話)會依外觀檢查,以找出適合例外狀況的處理常式。The catch clauses, if any, are examined in order of appearance to locate a suitable handler for the exception. 如果 catch 子句未指定類型,或指定例外狀況類型或例外狀況類型的基底類型:If a catch clause does not specify a type, or specifies the exception type or a base type of the exception type:
      • 如果 catch 子句宣告例外狀況變數,則會將例外狀況物件指派給例外狀況變數。If the catch clause declares an exception variable, the exception object is assigned to the exception variable.
      • 如果 catch 子句宣告例外狀況篩選準則,則會評估篩選。If the catch clause declares an exception filter, the filter is evaluated. 如果評估為 false ,則 catch 子句不相符,且搜尋會繼續執行 catch 適當處理常式的任何後續子句。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.
      • 否則, catch 子句會被視為相符,而且控制權會轉移至相符的 catch 區塊。Otherwise, the catch clause is considered a match, and control is transferred to the matching catch block.
      • 當和 if 控制項到達區塊的結束點時 catchWhen and if control reaches the end point of the catch block:
        • 如果 try 語句具有 finally 區塊,則 finally 會執行區塊。If the try statement has a finally block, the finally block is executed.
        • 控制權會傳送至語句的結束點 tryControl is transferred to the end point of the try statement.
      • 如果在執行區塊時,將例外狀況傳播至 try 語句 catchIf an exception is propagated to the try statement during execution of the catch block:
        • 如果 try 語句具有 finally 區塊,則 finally 會執行區塊。If the try statement has a finally block, the finally block is executed.
        • 例外狀況會傳播至下一個封入 try 語句。The exception is propagated to the next enclosing try statement.
    • 如果 try 語句沒有子句, catch 或如果沒有 catch 子句符合例外狀況:If the try statement has no catch clauses or if no catch clause matches the exception:
      • 如果 try 語句具有 finally 區塊,則 finally 會執行區塊。If the try statement has a finally block, the finally block is executed.
      • 例外狀況會傳播至下一個封入 try 語句。The exception is propagated to the next enclosing try statement.

finally當控制項離開語句時,一律會執行區塊的語句 tryThe statements of a finally block are always executed when control leaves a try statement. 無論是因為執行、、或語句而導致控制傳送發生, break continue goto return 或是因為將例外狀況傳播到 try 語句以外的結果,都是如此。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.

如果在執行區塊期間擲回例外狀況 finally ,而且不是在相同 finally 區塊內攔截,則例外狀況會傳播至下一個封入 try 語句。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. 如果正在傳播其他例外狀況,則會遺失該例外狀況。If another exception was in the process of being propagated, that exception is lost. 傳播例外狀況的處理常式會在 throw (throw 語句) 的語句描述中進一步討論。The process of propagating an exception is discussed further in the description of the throw statement (The throw statement).

try try 如果可以連線到語句,就可以連線到語句區塊 tryThe try block of a try statement is reachable if the try statement is reachable.

catch try 如果可以連線到語句,就可以連線到語句區塊 tryA catch block of a try statement is reachable if the try statement is reachable.

finally try 如果可以連線到語句,就可以連線到語句區塊 tryThe finally block of a try statement is reachable if the try statement is reachable.

try如果下列兩個條件成立,就可以連線到語句的結束點:The end point of a try statement is reachable if both of the following are true:

  • 區塊的結束點可供連線, try 或至少有一個區塊的結束點 catch 可供存取。The end point of the try block is reachable or the end point of at least one catch block is reachable.
  • 如果有 finally 區塊,就可以連線到區塊的結束點 finallyIf a finally block is present, the end point of the finally block is reachable.

checked 和 unchecked 陳述式The checked and unchecked statements

checkedunchecked 語句用來控制整數型別算數運算和轉換的 溢位檢查內容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
    ;

checked語句會使 區塊 中的所有運算式在已檢查的內容中進行評估,而 unchecked 語句會使 區塊 中的所有運算式都在未檢查的內容中進行評估。The checked statement causes all expressions in the block to be evaluated in a checked context, and the unchecked statement causes all expressions in the block to be evaluated in an unchecked context.

checkedunchecked 語句相當於 checked and unchecked 運算子, (checked 和 unchecked 運算子) ,只不過它們會在區塊而非運算式上運作。The checked and unchecked statements are precisely equivalent to the checked and unchecked operators (The checked and unchecked operators), except that they operate on blocks instead of expressions.

lock 陳述式The lock statement

語句會取得 lock 指定物件的互斥鎖定、執行語句,然後釋放鎖定。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
    ;

語句的運算式 lock 必須代表已知為 reference_type 的型別值。The expression of a lock statement must denote a value of a type known to be a reference_type. 在執行語句的運算式時,不會執行任何隱含的裝箱轉換 (的 裝箱轉換) lock ,因此它是編譯時期錯誤,運算式表示 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表單的語句A lock statement of the form

lock (x) ...

其中 xreference_type 的運算式,精確等於where x is an expression of a reference_type, is precisely equivalent to

bool __lockWasTaken = false;
try {
    System.Threading.Monitor.Enter(x, ref __lockWasTaken);
    ...
}
finally {
    if (__lockWasTaken) System.Threading.Monitor.Exit(x);
}

但只會評估 x 一次。except that x is only evaluated once.

當互斥鎖定被保留時,在相同執行執行緒中執行的程式碼也可以取得並釋放鎖定。While a mutual-exclusion lock is held, code executing in the same execution thread can also obtain and release the lock. 不過,在其他執行緒中執行的程式碼會被封鎖而無法取得鎖定,直到釋放鎖定為止。However, code executing in other threads is blocked from obtaining the lock until the lock is released.

System.Type不建議鎖定物件以同步存取靜態資料。Locking System.Type objects in order to synchronize access to static data is not recommended. 其他程式碼可能會鎖定相同的類型,這可能會導致鎖死。Other code might lock on the same type, which can result in deadlock. 更好的方法是鎖定私用靜態物件,以同步處理靜態資料的存取。A better approach is to synchronize access to static data by locking a private static object. 例如: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) {
            ...
        }
    }
}

using 陳述式The using statement

語句會取得 using 一或多個資源、執行語句,然後處置資源。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
    ;

資源 是實作為的類別或結構 System.IDisposable ,其中包含名為的單一無參數方法 DisposeA resource is a class or struct that implements System.IDisposable, which includes a single parameterless method named Dispose. 使用資源的程式碼可以呼叫 Dispose 來指出不再需要資源。Code that is using a resource can call Dispose to indicate that the resource is no longer needed. 如果 Dispose 未呼叫,則自動處置最後會因為垃圾收集而發生。If Dispose is not called, then automatic disposal eventually occurs as a consequence of garbage collection.

如果 resource_acquisition 的格式為 local_variable_declarationlocal_variable_declaration 的型別必須是 dynamic 或可隱含轉換成的型別 System.IDisposableIf 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. 如果 resource_acquisition 的形式為 expression ,則此運算式必須可隱含轉換成 System.IDisposableIf the form of resource_acquisition is expression then this expression must be implicitly convertible to System.IDisposable.

resource_acquisition 中宣告的區域變數是唯讀的,而且必須包含初始化運算式。Local variables declared in a resource_acquisition are read-only, and must include an initializer. 如果內嵌的語句嘗試透過指派或和運算子) 來修改這些區域變數 (++ -- 、取得其位址,或將它們當作 ref 或參數傳遞,就會發生編譯時期錯誤 outA 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語句會轉譯成三個部分:取得、使用和處置。A using statement is translated into three parts: acquisition, usage, and disposal. 資源的使用方式會以隱含方式包含在 try 包含子句的語句中 finallyUsage of the resource is implicitly enclosed in a try statement that includes a finally clause. 這個 finally 子句會處置資源。This finally clause disposes of the resource. 如果 null 取得資源,則不會進行任何呼叫 Dispose ,也不會擲回例外狀況。If a null resource is acquired, then no call to Dispose is made, and no exception is thrown. 如果資源的類型為,則 dynamic 會透過隱含動態轉換來動態轉換 (在取得期間) 的 隱含動態 轉換, IDisposable 以確保在使用和處置之前轉換成功。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表單的語句A using statement of the form

using (ResourceType resource = expression) statement

對應至三個可能的擴充之一。corresponds to one of three possible expansions. ResourceType 是不可為 null 的實值型別時,展開是When ResourceType is a non-nullable value type, the expansion is

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

否則,當 ResourceType 是可為 null 的實值型別或參考型別時 dynamic ,展開是Otherwise, when ResourceType is a nullable value type or a reference type other than dynamic, the expansion is

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

否則,當 ResourceType 為時 dynamic ,展開是Otherwise, when ResourceType is dynamic, the expansion is

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

在任一展開中, resource 變數在內嵌語句中都是唯讀的,而且 d 內嵌語句無法存取和隱藏變數。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.

您可以使用實值以不同的方式來執行指定的 using 語句,例如基於效能考慮,只要行為與上述擴充一致即可。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表單的語句A using statement of the form

using (expression) statement

有三個可能的擴充。has the same three possible expansions. 在此情況下 ResourceType ,會隱含的編譯時間類型 expression (如果有的話)。In this case ResourceType is implicitly the compile-time type of the expression, if it has one. 否則 IDisposable 會使用介面本身做為 ResourceTypeOtherwise the interface IDisposable itself is used as the ResourceType. resource內嵌語句無法存取和隱藏變數。The resource variable is inaccessible in, and invisible to, the embedded statement.

resource_acquisition 採用 local_variable_declaration 的形式時,就可以取得特定類型的多個資源。When a resource_acquisition takes the form of a local_variable_declaration, it is possible to acquire multiple resources of a given type. using表單的語句A using statement of the form

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

相當於一系列的嵌套 using 語句:is precisely equivalent to a sequence of nested using statements:

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

下列範例會建立名為的檔案 log.txt ,並將兩行文字寫入檔案。The example below creates a file named log.txt and writes two lines of text to the file. 然後,此範例會開啟該相同檔案,以讀取包含的文字行,並將其複製到主控台。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);
            }

        }
    }
}

由於 TextWriterTextReader 類別 IDisposable 會執行介面,因此範例可以使用語句, using 以確保在寫入或讀取作業之後,基礎檔案會正確關閉。Since the TextWriter and TextReader classes implement the IDisposable interface, the example can use using statements to ensure that the underlying file is properly closed following the write or read operations.

yield 陳述式The yield statement

yield語句會用在 iterator 區塊中, (區塊) 來產生列舉值物件的值 (列舉值物件) 或可列舉物件 (Iterator 的可列舉物件) 或表示反復專案的結尾。The yield statement is used in an iterator block (Blocks) to yield a value to the enumerator object (Enumerator objects) or enumerable object (Enumerable objects) of an iterator or to signal the end of the iteration.

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

yield 不是保留字;只有在或關鍵字之前立即使用時,才具有特殊意義 return breakyield is not a reserved word; it has special meaning only when used immediately before a return or break keyword. 在其他內容中, yield 可以使用做為識別碼。In other contexts, yield can be used as an identifier.

有幾項限制 yield 可顯示語句的位置,如下所述。There are several restrictions on where a yield statement can appear, as described in the following.

  • 這是 yield 語句 (的編譯時期錯誤,) 出現在 method_body 的外部, operator_bodyaccessor_bodyIt is a compile-time error for a yield statement (of either form) to appear outside a method_body, operator_body or accessor_body
  • 這是語句 (的編譯時期錯誤, yield) 出現在匿名函式內。It is a compile-time error for a yield statement (of either form) to appear inside an anonymous function.
  • 這是語句 (的編譯時期錯誤, yield) 會出現在 finally 語句的子句中 tryIt is a compile-time error for a yield statement (of either form) to appear in the finally clause of a try statement.
  • 這是編譯時期錯誤, yield return 語句會出現在 try 包含任何子句的語句中的任何位置 catchIt is a compile-time error for a yield return statement to appear anywhere in a try statement that contains any catch clauses.

下列範例顯示語句的一些有效和無效用法 yieldThe 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
}

隱含轉換 (隱含 轉換) 必須從語句中的運算式類型 yield return ,到反覆運算器 (yield 型 別) 的 yield 型別。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語句的執行方式如下:A yield return statement is executed as follows:

  • 語句中指定的運算式會進行評估、隱含轉換成 yield 型別,然後指派給 Current 列舉值物件的屬性。The expression given in the statement is evaluated, implicitly converted to the yield type, and assigned to the Current property of the enumerator object.
  • 反覆運算器區塊的執行已暫止。Execution of the iterator block is suspended. 如果 yield return 語句在一或多個 try 區塊中, finally 就不會在此時間執行相關聯的區塊。If the yield return statement is within one or more try blocks, the associated finally blocks are not executed at this time.
  • MoveNext列舉值物件的方法會 true 傳回給它的呼叫者,表示列舉值物件已成功前進到下一個專案。The MoveNext method of the enumerator object returns true to its caller, indicating that the enumerator object successfully advanced to the next item.

下一次呼叫列舉值物件的 MoveNext 方法時,會繼續從上次暫停的位置執行 iterator 區塊。The next call to the enumerator object's MoveNext method resumes execution of the iterator block from where it was last suspended.

yield break語句的執行方式如下:A yield break statement is executed as follows:

  • 如果 yield break 語句是以一個或多個 try 具有相關聯區塊的區塊括住 finally ,則會一開始就將控制權轉移到 finally 最內層的 try 語句區塊。If the yield break statement is enclosed by one or more try blocks with associated finally blocks, control is initially transferred to the finally block of the innermost try statement. 當和 if 控制項到達區塊的結束點時 finally ,控制權會轉移到 finally 下一個封入語句的區塊 tryWhen and if control reaches the end point of a finally block, control is transferred to the finally block of the next enclosing try statement. 此程式會重複執行,直到 finally 所有封閉語句的區塊 try 都已執行為止。This process is repeated until the finally blocks of all enclosing try statements have been executed.
  • 控制權會傳回 iterator 區塊的呼叫端。Control is returned to the caller of the iterator block. 這可能是 MoveNext 列舉值物件的方法或 Dispose 方法。This is either the MoveNext method or Dispose method of the enumerator object.

因為 yield break 語句會無條件地將控制權傳送到其他地方,所以 yield break 永遠不會到達語句的結束點。Because a yield break statement unconditionally transfers control elsewhere, the end point of a yield break statement is never reachable.