陳述式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而非陳述式其如果分支。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運算式陳述式因為區塊F方法可連線。The 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? '}'
    ;

A區塊包含選擇性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. 時,並控制到達結束點的陳述式清單,控制權會轉移到區塊的結束點。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.

A區塊,其中包含一或多個yield陳述式 (yield 陳述式) 呼叫迭代器區塊。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). 一些其他的限制將套用至迭代器區塊:Some additional restrictions apply to iterator blocks:

  • 它是編譯時期錯誤return才會出現在迭代器區塊的陳述式 (但yield return允許陳述式)。It is a compile-time error for a return statement to appear in an iterator block (but yield return statements are permitted).
  • 它是迭代器區塊包含不安全的內容的編譯時間錯誤 (Unsafe 內容)。It is a compile-time error for an iterator block to contain an unsafe context (Unsafe contexts). 迭代器區塊一律會定義安全的內容中,即使其宣告為巢狀方式置於不安全的內容。An iterator block always defines a safe context, even when its declaration is nested in an unsafe context.

陳述式清單Statement lists

A陳述式清單順序中編寫的一或多個陳述式所組成。A statement list consists of one or more statements written in sequence. 陳述式清單中發生區塊s (區塊) 並在switch_blocks (switch 陳述式)。Statement lists occur in blocks (Blocks) and in switch_blocks (The switch statement).

statement_list
    : statement+
    ;

將控制權傳輸至第一個陳述式時,會執行陳述式清單。A statement list is executed by transferring control to the first statement. 時,並控制到達結束點,陳述式,控制權會轉移至下一個陳述式。When and if control reaches the end point of a statement, control is transferred to the next statement. 時,並控制到達結束點的最後一個陳述式,控制權會轉移至陳述式清單的結束點。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.

寫入時,就可以使用空的陳述式whilenull 主體陳述式:An 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

A 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
    ;

Labeled 陳述式使用指定的名稱會宣告一個標籤識別碼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.

除了一般控制流程所提供的連線能力,加上標籤的陳述式是如果標籤參考可連線到goto陳述式。In addition to the reachability provided by normal flow of control, a labeled statement is reachable if the label is referenced by a reachable goto statement. (例外狀況:如果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

A 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

A 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_typelocal_variable_declaration直接指定變數的宣告所引進的類型,或具有識別項表示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_declarators,其中每一個導入了新的變數。The type is followed by a list of local_variable_declarators, each of which introduces a new variable. A local_variable_declarator組成識別項可命名變數,並且選擇性地加 」="語彙基元和local_variable_initializer提供變數的初始值。A local_variable_declarator consists of an identifier that names the variable, optionally followed by an "=" token and a local_variable_initializer that gives the initial value of the variable.

在區域變數宣告的內容中,識別碼 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_declarators。The local_variable_declaration cannot include multiple local_variable_declarators.
  • 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

A 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_declarators,其中每一個導入了新的常數。The type is followed by a list of constant_declarators, each of which introduces a new constant. A constant_declarator組成識別項該名稱的常數,後面加上 「="語彙基元,後面接著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_declaratorIt 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 + yx == 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_statementExecution of an expression_statement evaluates the contained expression and then transfers control to the end point of the expression_statement. 結束點expression_statement連線,如果該expression_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部分是語彙最接近的前面加上相關聯if所允許的語法。An 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陳述式。When 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陳述式。When and if control reaches the end point of that statement, control is transferred to the end point of the if statement.
  • 如果布林運算式會產生false而如果else組件不存在,控制權會轉移至結束點if陳述式。If the boolean expression yields false and if an else part is not present, control is transferred to the end point of the if statement.

第一個內嵌的陳述式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 運算式的值相關聯的參數標籤的陳述式清單。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' ':'
    ;

A 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_sections,大括號括住。The switch_block consists of zero or more switch_sections, enclosed in braces. 每個switch_section包含一個或多個switch_labels 後面statement_list (陳述式會列出)。Each switch_section consists of one or more switch_labels followed by a statement_list (Statement lists).

型別來控管switch陳述式會建立 switch 運算式的方法。The governing type of a switch statement is established by the switch expression.

  • 對 switch 運算式的類型是否sbytebyteshortushortintuintlongulongboolcharstring,或enum_type,或如果它是可為 null 的型別對應至其中一個類型,則這是在管理類型switch陳述式。If the type of the switch expression is sbyte, byte, short, ushort, int, uint, long, ulong, bool, char, string, or an enum_type, or if it is the nullable type corresponding to one of these types, then that is the governing type of the switch statement.
  • 否則,只有一個使用者定義的隱含轉換 (使用者定義轉換) 控管類型的下列可能的其中一個 switch 運算式的類型必須存在: sbytebyteshort``ushortintuintlongulongcharstring,或為 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標籤必須表示為隱含轉換的值 (隱含轉換) 的控管的型別switch陳述式。The constant expression of each case label must denote a value that is implicitly convertible (Implicit conversions) to the governing type of the switch statement. 如果兩個或多個,就會發生編譯時期錯誤case標籤在同一個switch陳述式指定相同的常數值。A compile-time error occurs if two or more case labels in the same switch statement specify the same constant value.

可以有最多一個defaultswitch 陳述式中的標籤。There can be at most one default label in a switch statement.

Aswitch陳述式,如下所示:A switch statement is executed as follows:

  • Switch 運算式會評估,並控管的型別轉換。The switch expression is evaluated and converted to the governing type.
  • 如果在指定的其中一個常數case標籤在同一個switch陳述式是對 switch 運算式的值相等,控制權會轉移到下列相符的陳述式清單case標籤。If one of the constants specified in a case label in the same switch statement is equal to the value of the switch expression, control is transferred to the statement list following the matched case label.
  • 如果沒有在指定的常數case標籤在同一個switch陳述式會等於 switch 運算式的值,才default標籤存在,則控制權會轉移到之後的陳述式清單default標籤。If none of the constants specified in case labels in the same switch statement is equal to the value of the switch expression, and if a default label is present, control is transferred to the statement list following the default label.
  • 如果沒有任何常數中指定case標籤在同一個switch陳述式會等於 switch 運算式的值,如果沒有default標籤存在,則控制權會轉移至結束點switch陳述式。If none of the constants specified in case labels in the same switch statement is equal to the value of the switch expression, and if no default label is present, control is transferred to the end point of the switch statement.

如果陳述式清單的參數區段的結束點連線到,就會發生編譯時期錯誤。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;
}

因為沒有 switch 區段具有可聯繫的端點,則會有效。is valid because no switch section has a reachable end point. 不同於 C 和C++,執行的 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 區段時接著執行另一個交換器區段,明確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_sectionMultiple 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_sectionThe 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++時break不小心省略陳述式。The "no fall through" rule prevents a common class of bugs that occur in C and C++ when break statements are accidentally omitted. 此外,因為這項規則的參數區段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;
}

陳述式清單的參數區段通常結尾breakgoto case,或goto 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陳述式會區分大小寫和參數的運算式字串完全相符時,才會執行指定的參數區段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.

Statement_listswitch_block可能包含宣告陳述式 (宣告陳述式)。The statement_lists 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參數區段中的標籤。The switch expression is a constant value that matches a case label in the switch section.
  • Switch 運算式是常數值不符合任何case標籤和 [參數] 區段包含default標籤。The switch expression is a constant value that doesn't match any case label, and the switch section contains the default label.
  • 可存取參考的參數區段的參數標籤goto casegoto default陳述式。A 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陳述式,結束switch陳述式。The 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
    ;

Awhile陳述式,如下所示: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. 時,並控制到達內嵌的陳述式的結束點 (可能是從執行continue陳述式),控制權會轉移到開頭while陳述式。When and if control reaches the end point of the embedded statement (possibly from execution of a continue statement), control is transferred to the beginning of the while statement.
  • 如果布林運算式會產生false,控制權會轉移至結束點while陳述式。If the boolean expression yields false, control is transferred to the end point of the while statement.

內嵌的陳述式內while陳述式中,break陳述式 (break 陳述式) 可用來將控制權移轉給結束點while(因而結束反覆項目內嵌的陳述式陳述式),以及continue陳述式 (continue 陳述式) 可用來將控制權移轉給內嵌的陳述式的結束點 (藉此來執行的另一個反覆項目while陳述式)。Within the embedded statement of a while statement, a break statement (The break statement) may be used to transfer control to the end point of the while statement (thus ending iteration of the embedded statement), and a continue statement (The continue statement) may be used to transfer control to the end point of the embedded statement (thus performing another iteration of the while statement).

內嵌的陳述式的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陳述式,結束while陳述式。The 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 ')' ';'
    ;

Ado陳述式,如下所示:A do statement is executed as follows:

  • 控制權會轉移到內嵌的陳述式。Control is transferred to the embedded statement.
  • 時,並控制到達內嵌的陳述式的結束點 (可能是從執行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,控制權會轉移到開頭do陳述式。If the boolean expression yields true, control is transferred to the beginning of the do statement. 否則,控制權會轉移到結束點do陳述式。Otherwise, control is transferred to the end point of the do statement.

內嵌的陳述式內do陳述式中,break陳述式 (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陳述式是連線到如果do陳述式。The 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陳述式,結束do陳述式。The 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.

陳述式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_運算式s (運算式陳述式) 以逗號分隔。The for_initializer, if present, consists of either a local_variable_declaration (Local variable declarations) or a list of statement_expressions (Expression statements) separated by commas. 所宣告的本機變數的範圍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_expressions (運算式陳述式) 以逗號分隔。The for_iterator, if present, consists of a list of statement_expressions (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. 時,並控制到達內嵌的陳述式的結束點 (可能是從執行continue陳述式),運算式for_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,控制權會轉移至結束點for陳述式。If the for_condition is present and the evaluation yields false, control is transferred to the end point of the for statement.

內嵌的陳述式內for陳述式中,break陳述式 (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陳述式和 no 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陳述式,結束for陳述式。The 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. 如果內嵌的陳述式嘗試修改反覆項目變數,就會發生編譯時期錯誤 (透過指派或++--運算子),或傳遞的反覆項目變數refout參數。A compile-time error occurs if the embedded statement attempts to modify the iteration variable (via assignment or the ++ and -- operators) or pass the iteration variable as a ref or out parameter.

在下列命令,為求簡潔, IEnumerableIEnumeratorIEnumerable<T>IEnumerator<T>命名空間中的對應類型是指System.CollectionsSystem.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運算式是陣列型別,則會從隱含參考轉換XIEnumerable介面 (因為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.
    • 如果傳回型別EGetEnumerator方法不是類別、 結構或介面類型時,錯誤會產生並採取任何進一步的步驟。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,和項目型別是種Current屬性。The 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包括不的隱含轉換XIEnumerable<Ti>,沒有唯一的型別T使得T不是dynamic和其他所有Ti沒有隱含轉換IEnumerable<T>IEnumerable<Ti>,則集合型別介面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.
    • 否則,如果沒有隱含轉換XSystem.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( local_variable_type foreach 陳述式中),會產生錯誤也採取任何進一步的步驟。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.

放置v內 while 迴圈是很重要的擷取所發生的任何匿名函式的方式embedded_statementThe 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();

如果vdeklarovalo 之外 while 迴圈中,它會共用所有的反覆項目,以及它的值之後迴圈會是最後的值, 13,這是什麼引動過程的f會列印。If v was declared outside of the while loop, it would be shared among all iterations, and its value after the for loop would be the final value, 13, which is what the invocation of f would print. 相反地,因為每個反覆項目有它自己的變數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.)

本文最後的區塊建構根據下列步驟:The body of the finally block is constructed according to the following steps:

  • 如果沒有隱含轉換ESystem.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是實值型別或實值類型,然後轉型的具現化的型別參數eSystem.IDisposable不會發生 boxing。except that if E is a value type, or a type parameter instantiated to a value type, then the cast of e to System.IDisposable will not cause boxing to occur.

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

    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.

跳躍陳述式的執行複雜的中介try陳述式。Execution 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. 時,並控制到達結束點finally區塊中,控制傳輸至finally區塊下一步 的封入try陳述式。When and if control reaches the end point of a finally block, control is transferred to the finally block of the next enclosing try statement. 此程序會重複直到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陳述式會結束最內層switchwhiledofor,或foreach陳述式。The break statement exits the nearest enclosing switch, while, do, for, or foreach statement.

break_statement
    : 'break' ';'
    ;

目標break陳述式會結束點的最接近的封閉式switchwhiledofor,或foreach陳述式。The target of a break statement is the end point of the nearest enclosing switch, while, do, for, or foreach statement. 如果break陳述式不加switchwhiledofor,或foreach陳述式,會發生編譯時期錯誤。If a break statement is not enclosed by a switch, while, do, for, or foreach statement, a compile-time error occurs.

當多個switchwhiledofor,或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.

Abreak陳述式無法結束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.

Abreak陳述式,如下所示: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. 時,並控制到達結束點finally區塊中,控制傳輸至finally區塊下一步 的封入try陳述式。When and if control reaches the end point of a finally block, control is transferred to the finally block of the next enclosing try statement. 此程序會重複直到finally的所有區塊中介try陳述式執行。This process is repeated until the finally blocks of all intervening try statements have been executed.
  • 控制權會轉移到目標的break陳述式。Control 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陳述式開始執行新的反覆查看的最接近的封閉式whiledofor,或foreach陳述式。The continue statement starts a new iteration of the nearest enclosing while, do, for, or foreach statement.

continue_statement
    : 'continue' ';'
    ;

目標continue陳述式是內嵌的陳述式的最接近的封閉式終點whiledofor,或foreach陳述式。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陳述式不加whiledofor,或foreach陳述式,會發生編譯時期錯誤。If a continue statement is not enclosed by a while, do, for, or foreach statement, a compile-time error occurs.

當多個whiledofor,或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.

Acontinue陳述式無法結束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.

Acontinue陳述式,如下所示: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. 時,並控制到達結束點finally區塊中,控制傳輸至finally區塊下一步 的封入try陳述式。When and if control reaches the end point of a finally block, control is transferred to the finally block of the next enclosing try statement. 此程序會重複直到finally的所有區塊中介try陳述式執行。This process is repeated until the finally blocks of all intervening try statements have been executed.
  • 控制權會轉移到目標的continue陳述式。Control 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識別碼陳述式是以指定標記的標記陳述式。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 陳述式),其中包含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.

Agoto陳述式無法結束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.

Agoto陳述式,如下所示: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. 時,並控制到達結束點finally區塊中,控制傳輸至finally區塊下一步 的封入try陳述式。When and if control reaches the end point of a finally block, control is transferred to the finally block of the next enclosing try statement. 此程序會重複直到finally的所有區塊中介try陳述式執行。This process is repeated until the finally blocks of all intervening try statements have been executed.
  • 控制權會轉移到目標的goto陳述式。Control 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陳述式將控制權傳回給目前的呼叫端函式所在的return陳述式隨即出現。The return statement returns control to the current caller of the function in which the return statement appears.

return_statement
    : 'return' expression? ';'
    ;

Areturn但沒有運算式的陳述式只能用於不會計算值時,也就是方法的結果類型的函式成員 (方法主體) void,則set屬性存取子或索引子addremove存取子的事件、 執行個體建構函式、 靜態建構函式或解構函式。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.

Areturn陳述式的運算式只能在計算值,也就是具有非 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 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).

Areturn陳述式,如下所示: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陳述式會包含一或多個try或是catch區塊相關聯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. 時,並控制到達結束點finally區塊中,控制傳輸至finally區塊下一步 的封入try陳述式。When and if control reaches the end point of a finally block, control is transferred to the finally block of the next enclosing try statement. 此程序會重複直到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.
  • 如果包含的函式是 async 函式,控制權給目前的呼叫端,而且結果值,如果有的話,會記錄在傳回的工作中所述 (列舉程式介面)。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? ';'
    ;

Athrow與運算式的陳述式會擲回的評估運算式所產生的值。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.

Athrow但沒有運算式的陳述式可以只能用於catch封鎖,請在此情況下該陳述式重新擲回例外狀況正在處理由該catch區塊。A throw statement with no expression can be used only in a catch block, in which case that statement re-throws the exception that is currently being handled by that catch block.

因為throw陳述式無條件地將控制權傳輸其他位置、 結束點throw陳述式絕不會是可連線。Because a throw statement unconditionally transfers control elsewhere, the end point of a throw statement is never reachable.

擲回例外狀況時,控制權會轉移到第一個catch子句中為封入try可以處理的例外狀況的陳述式。When 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圍住擲回點與 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子句,藉由將控制權傳輸至該區塊完成例外狀況傳播catch子句。If 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.

    • 如果目前的函式是 async 和傳回工作,例外狀況會記錄在傳回的工作中,放入發生錯誤或已取消狀態中所述列舉程式介面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.

    • 如果目前的函式是 async 和傳回 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陳述式讓您能夠指定程式碼一律會執行,當控制離開區塊try陳述式。Furthermore, the try statement provides the ability to specify a block of code that is always executed when control leaves the try statement.

try_statement
    : 'try' block catch_clause+
    | 'try' block finally_clause
    | 'try' block catch_clause+ finally_clause
    ;

catch_clause
    : 'catch' exception_specifier? exception_filter?  block
    ;

exception_specifier
    : '(' type identifier? ')'
    ;

exception_filter
    : 'when' '(' expression ')'
    ;

finally_clause
    : 'finally' block
    ;

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

  • Atry區塊後面接著一或多個catch區塊。A try block followed by one or more catch blocks.
  • Atry區塊後面finally區塊。A try block followed by a finally block.
  • Atry區塊後面接著一或多個catch區塊後面finally區塊。A 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具有識別碼,則例外狀況變數宣告指定名稱和類型。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子句會包含例外狀況變數名稱,就無法存取在篩選中的例外狀況物件和catch區塊。Unless a catch clause includes an exception variable name, it is impossible to access the exception object in the filter and catch block.

Acatch未指定的子句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子句,try陳述式。If a catch clause specifies no type and no filter, it must be the last catch clause for that try statement.

catch區塊中,throw陳述式 (throw 陳述式) 沒有運算式可以用來重新擲回已攔截的例外狀況catch區塊。Within a catch block, a throw statement (The throw statement) with no expression can be used to re-throw the exception that was caught by the catch block. 例外狀況變數的指派不會改變會重新擲回的例外狀況。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陳述式時的控制權轉移finally區塊。It is a compile-time error for a break, continue, or goto statement to transfer control out of a finally block. breakcontinue,或goto陳述式中發生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陳述式中發生finally區塊。It is a compile-time error for a return statement to occur in a finally block.

Atry陳述式,如下所示:A try statement is executed as follows:

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

  • 時,並控制到達結束點try區塊:When 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.
    • 控制權會轉移至結束點try陳述式。Control is transferred to the end point of the try statement.
  • 如果例外狀況會傳播到try陳述式執行期間try區塊:If 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.
      • 時,並控制到達結束點catch區塊:When 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.
        • 控制權會轉移至結束點try陳述式。Control is transferred to the end point of the try statement.
      • 如果例外狀況會傳播到try陳述式執行期間catch區塊:If 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當控制離開區塊一律會執行try陳述式。The statements of a finally block are always executed when control leaves a try statement. 這適用於控制傳輸是否正常執行,因為執行的結果就會發生breakcontinuegoto,或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陳述式是連線到如果try陳述式。The try block of a try statement is reachable if the try statement is reachable.

Acatch區塊try陳述式是連線到如果try陳述式。A catch block of a try statement is reachable if the try statement is reachable.

finally區塊try陳述式是連線到如果try陳述式。The 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區塊已存在,結束點finally區塊可連線。If 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陳述式會都導致中的所有運算式區塊来進行評估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陳述式是相當於checkedunchecked運算子 (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_typeThe expression of a lock statement must denote a value of a type known to be a reference_type. 沒有任何隱含 boxing 轉換 (Boxing 轉換) 的運算式執行曾執行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.

Alock表單的陳述式A lock statement of the form

lock (x) ...

何處x是的運算式reference_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
    ;

A resource是類別或結構實作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_acquisitionlocal_variable_declaration然後的型別local_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運算式則此運算式必須是隱含地轉換成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. 如果內嵌的陳述式嘗試修改這些本機變數,就會發生編譯時期錯誤 (透過指派或++--運算子)、 取得位址,或將其做為傳遞refout參數。A compile-time error occurs if the embedded statement attempts to modify these local variables (via assignment or the ++ and -- operators) , take the address of them, or pass them as ref or out parameters.

Ausing陳述式會轉譯成三個部分︰ 取得、 使用量以及各種可供使用。A using statement is translated into three parts: acquisition, usage, and disposal. 使用資源以隱含方式住try陳述式,其中包含finally子句。Usage 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.

Ausing表單的陳述式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();
    }
}

否則,當ResourceTypedynamic,擴充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.

Ausing表單的陳述式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. Ausing表單的陳述式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 區塊 (區塊) 來產生列舉值物件的值 (列舉值物件) 或可列舉的物件 (的可列舉物件)迭代器,或表示反覆項目結束。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 不是保留的字;它具有特殊意義之前,立即使用時,才returnbreak關鍵字。yield 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_bodyoperator_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子句try陳述式。It 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陳述式,其中包含所有catch子句。It is a compile-time error for a yield return statement to appear anywhere in a try statement that contains any catch clauses.

下列範例示範一些有效和無效使用yield陳述式。The following example shows some valid and invalid uses of yield statements.

delegate IEnumerable<int> D();

IEnumerator<int> GetEnumerator() {
    try {
        yield return 1;        // Ok
        yield break;           // Ok
    }
    finally {
        yield return 2;        // Error, yield in finally
        yield break;           // Error, yield in finally
    }

    try {
        yield return 3;        // Error, yield return in try...catch
        yield break;           // Ok
    }
    catch {
        yield return 4;        // Error, yield return in try...catch
        yield break;           // Ok
    }

    D d = delegate { 
        yield return 5;        // Error, yield in an anonymous function
    }; 
}

int MyMethod() {
    yield return 1;            // Error, wrong return type for an iterator block
}

隱含的轉換 (隱含轉換) 中的運算式的型別必須存在於yield return陳述式來產生型別 (產生類型) 迭代器。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.

Ayield return陳述式,如下所示:A yield return statement is executed as follows:

  • 陳述式中指定的運算式會評估,以隱含方式轉換產生的型別,並指派給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.

Enumerator 物件的下一個呼叫MoveNext方法繼續執行從上次已中暫止的迭代器區塊。The next call to the enumerator object's MoveNext method resumes execution of the iterator block from where it was last suspended.

Ayield 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. 時,並控制到達結束點finally區塊中,控制傳輸至finally區塊下一步 的封入try陳述式。When and if control reaches the end point of a finally block, control is transferred to the finally block of the next enclosing try statement. 此程序會重複直到finally區塊的所有封入try陳述式執行。This process is repeated until the finally blocks of all enclosing try statements have been executed.
  • 程式控制權回到呼叫端的迭代器區塊。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.