日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > C# >内容正文

C#

C#6.0语言规范(八) 语句

發(fā)布時(shí)間:2024/1/17 C# 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C#6.0语言规范(八) 语句 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

C#提供了各種語(yǔ)句。大多數(shù)這些語(yǔ)句對(duì)于使用C和C ++編程的開(kāi)發(fā)人員來(lái)說(shuō)都很熟悉。

1 statement 2 : labeled_statement 3 | declaration_statement 4 | embedded_statement 5 ; 6 7 embedded_statement 8 : block 9 | empty_statement 10 | expression_statement 11 | selection_statement 12 | iteration_statement 13 | jump_statement 14 | try_statement 15 | checked_statement 16 | unchecked_statement 17 | lock_statement 18 | using_statement 19 | yield_statement 20 | embedded_statement_unsafe 21 ;

該embedded_statement非終結(jié)用于出現(xiàn)其他語(yǔ)句中的語(yǔ)句。使用embedded_statement而不是語(yǔ)句排除了在這些上下文中使用聲明語(yǔ)句和帶標(biāo)簽的語(yǔ)句。這個(gè)例子

1 void F(bool b) { 2 if (b) 3 int i = 44; 4 }

導(dǎo)致編譯時(shí)錯(cuò)誤,因?yàn)閕f語(yǔ)句需要embedded_statement而不是if分支的語(yǔ)句。如果允許此代碼,則會(huì)i聲明變量,但永遠(yuǎn)不會(huì)使用它。但請(qǐng)注意,通過(guò)i在塊中放置聲明,該示例是有效的。

終點(diǎn)和可達(dá)性

每個(gè)陳述都有一個(gè)終點(diǎn)。直觀地說(shuō),語(yǔ)句的結(jié)束點(diǎn)是緊跟語(yǔ)句的位置。復(fù)合語(yǔ)句(包含嵌入語(yǔ)句的語(yǔ)句)的執(zhí)行規(guī)則指定控件到達(dá)嵌入語(yǔ)句的結(jié)束點(diǎn)時(shí)所采取的操作。例如,當(dāng)控件到達(dá)塊中語(yǔ)句的結(jié)束點(diǎn)時(shí),控制權(quán)將轉(zhuǎn)移到塊中的下一個(gè)語(yǔ)句。

如果可以通過(guò)執(zhí)行來(lái)達(dá)到語(yǔ)句,則說(shuō)該語(yǔ)句是可訪問(wèn)的。相反,如果不可能執(zhí)行語(yǔ)句,則說(shuō)該語(yǔ)句無(wú)法訪問(wèn)。

在這個(gè)例子中

1 void F() { 2 Console.WriteLine("reachable"); 3 goto Label; 4 Console.WriteLine("unreachable"); 5 Label: 6 Console.WriteLine("reachable"); 7 }

第二次調(diào)用Console.WriteLine是無(wú)法訪問(wèn)的,因?yàn)椴豢赡軋?zhí)行該語(yǔ)句。

如果編譯器確定語(yǔ)句無(wú)法訪問(wèn),則會(huì)報(bào)告警告。聲明無(wú)法訪問(wèn)并不是錯(cuò)誤。

要確定特定語(yǔ)句或端點(diǎn)是否可訪問(wèn),編譯器將根據(jù)為每個(gè)語(yǔ)句定義的可訪問(wèn)性規(guī)則執(zhí)行流分析。流分析考慮了控制語(yǔ)句行為的常量表達(dá)式(常量表達(dá)式)的值,但不考慮非常量表達(dá)式的可能值。換句話說(shuō),出于控制流分析的目的,給定類(lèi)型的非常量表達(dá)式被認(rèn)為具有該類(lèi)型的任何可能值。

在這個(gè)例子中

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

if語(yǔ)句的布爾表達(dá)式是一個(gè)常量表達(dá)式,因?yàn)檫\(yùn)算==符的兩個(gè)操作數(shù)都是常量。由于常量表達(dá)式是在編譯時(shí)計(jì)算的,因此生成該值時(shí)false,Console.WriteLine調(diào)用被視為無(wú)法訪問(wèn)。但是,如果i將其更改為局部變量

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

在Console.WriteLine調(diào)用被認(rèn)為是可到達(dá)的,即使在現(xiàn)實(shí)中,它永遠(yuǎn)不會(huì)被執(zhí)行。

功能成員的塊始終被視為可訪問(wèn)。通過(guò)連續(xù)評(píng)估塊中每個(gè)語(yǔ)句的可達(dá)性規(guī)則,可以確定任何給定語(yǔ)句的可達(dá)性。

在這個(gè)例子中

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

第二個(gè)的可達(dá)性Console.WriteLine確定如下:

  • 第一個(gè)Console.WriteLine表達(dá)式語(yǔ)句是可到達(dá)的,因?yàn)樵揊方法的塊是可訪問(wèn)的。
  • Console.WriteLine可以訪問(wèn)第一個(gè)表達(dá)式語(yǔ)句的結(jié)束點(diǎn),因?yàn)樵撜Z(yǔ)句是可訪問(wèn)的。
  • 該if語(yǔ)句是可訪問(wèn)的,因?yàn)榈谝粋€(gè)Console.WriteLine表達(dá)式語(yǔ)句的結(jié)束點(diǎn)是可到達(dá)的。
  • 第二個(gè)Console.WriteLine表達(dá)式語(yǔ)句是可到達(dá)的,因?yàn)檎Z(yǔ)句的布爾表達(dá)式if沒(méi)有常量值false。

在兩種情況下,語(yǔ)句的結(jié)束點(diǎn)可以訪問(wèn)是編譯時(shí)錯(cuò)誤:

  • 因?yàn)樵搒witch語(yǔ)句不允許切換部分“通過(guò)”到下一個(gè)切換部分,所以切換部分的語(yǔ)句列表的結(jié)束點(diǎn)可以到達(dá)是編譯時(shí)錯(cuò)誤。如果發(fā)生此錯(cuò)誤,通常表示break缺少語(yǔ)句。
  • 它是函數(shù)成員塊的結(jié)束點(diǎn)的編譯時(shí)錯(cuò)誤,它計(jì)算可以訪問(wèn)的值。如果發(fā)生此錯(cuò)誤,則通常表示return缺少語(yǔ)句。

一個(gè)塊允許在一個(gè)單一的語(yǔ)句允許上下文中編寫(xiě)多條語(yǔ)句。

1 block 2 : '{' statement_list? '}' 3 ;

一個(gè)塊由一個(gè)可選的statement_list(語(yǔ)句列表)組成,括在括號(hào)中。如果省略語(yǔ)句列表,則該塊被認(rèn)為是空的。

一個(gè)塊可能包含聲明語(yǔ)句(聲明聲明)。塊中聲明的局部變量或常量的范圍是塊。

塊執(zhí)行如下:

  • 如果塊為空,則控制轉(zhuǎn)移到塊的結(jié)束點(diǎn)。
  • 如果塊不為空,則將控制轉(zhuǎn)移到語(yǔ)句列表。當(dāng)控制到達(dá)語(yǔ)句列表的結(jié)束點(diǎn)時(shí),控制轉(zhuǎn)移到塊的結(jié)束點(diǎn)。

如果塊本身可訪問(wèn),則可以訪問(wèn)塊的語(yǔ)句列表。

如果塊為空或者可以訪問(wèn)語(yǔ)句列表的結(jié)束點(diǎn),則可以訪問(wèn)塊的結(jié)束點(diǎn)。

阿塊包含一個(gè)或多個(gè)yield語(yǔ)句(yield語(yǔ)句)被稱為迭代器塊。迭代器塊用于將函數(shù)成員實(shí)現(xiàn)為迭代器(迭代器)。迭代器塊有一些額外的限制:

  • return語(yǔ)句出現(xiàn)在迭代器塊中是一個(gè)編譯時(shí)錯(cuò)誤(但yield return允許使用語(yǔ)句)。
  • 迭代器塊包含不安全的上下文(Unsafe contexts)是編譯時(shí)錯(cuò)誤。迭代器塊總是定義一個(gè)安全上下文,即使它的聲明嵌套在不安全的上下文中也是如此。

語(yǔ)句列表

一個(gè)語(yǔ)句列表由順序?qū)懭氲囊粋€(gè)或多個(gè)語(yǔ)句。語(yǔ)句列表出現(xiàn)在塊?s(塊)和switch_blocks(switch語(yǔ)句)中。

1 statement_list 2 : statement+ 3 ;

通過(guò)將控制轉(zhuǎn)移到第一個(gè)語(yǔ)句來(lái)執(zhí)行語(yǔ)句列表。當(dāng)控制到達(dá)語(yǔ)句的結(jié)束點(diǎn)時(shí),控制權(quán)轉(zhuǎn)移到下一個(gè)語(yǔ)句。當(dāng)控制到達(dá)最后一個(gè)語(yǔ)句的結(jié)束點(diǎn)時(shí),控制權(quán)轉(zhuǎn)移到語(yǔ)句列表的結(jié)束點(diǎn)。

如果至少滿足下列條件之一,則可以訪問(wèn)語(yǔ)句列表中的語(yǔ)句:

  • 該語(yǔ)句是第一個(gè)語(yǔ)句,語(yǔ)句列表本身是可訪問(wèn)的。
  • 可以訪問(wèn)上一個(gè)語(yǔ)句的結(jié)束點(diǎn)。
  • 該語(yǔ)句是帶標(biāo)簽的語(yǔ)句,標(biāo)簽由可訪問(wèn)的goto語(yǔ)句引用。

如果列表中最后一個(gè)語(yǔ)句的結(jié)束點(diǎn)可達(dá),則可以訪問(wèn)語(yǔ)句列表的結(jié)束點(diǎn)。

空語(yǔ)句

一個(gè)empty_statement什么都不做。

1 empty_statement 2 : ';' 3 ;

如果在需要語(yǔ)句的上下文中沒(méi)有要執(zhí)行的操作,則使用空語(yǔ)句。

執(zhí)行空語(yǔ)句只是將控制轉(zhuǎn)移到語(yǔ)句的結(jié)束點(diǎn)。因此,如果可以訪問(wèn)空語(yǔ)句,則可以訪問(wèn)空語(yǔ)句的結(jié)束點(diǎn)。

使用while?null主體編寫(xiě)語(yǔ)句時(shí)可以使用空語(yǔ)句:

1 bool ProcessMessage() {...} 2 3 void ProcessMessages() { 4 while (ProcessMessage()) 5 ; 6 }

此外,可以使用空語(yǔ)句}在塊的結(jié)束“?”?之前聲明標(biāo)簽:

1 void F() { 2 ... 3 if (done) goto exit; 4 ... 5 exit: ; 6 }

標(biāo)簽語(yǔ)句

一個(gè)labeled_statement允許一個(gè)標(biāo)簽作為前綴的聲明。塊中允許使用帶標(biāo)簽的語(yǔ)句,但不允許使用嵌入語(yǔ)句。

1 labeled_statement 2 : identifier ':' statement 3 ;

帶標(biāo)簽的語(yǔ)句聲明一個(gè)標(biāo)簽,其名稱由標(biāo)識(shí)符指定。標(biāo)簽的范圍是聲明標(biāo)簽的整個(gè)塊,包括任何嵌套塊。具有相同名稱的兩個(gè)標(biāo)簽具有重疊范圍是編譯時(shí)錯(cuò)誤。

可以從標(biāo)簽范圍內(nèi)的goto語(yǔ)句(goto語(yǔ)句)引用標(biāo)簽。這意味著goto語(yǔ)句可以在塊內(nèi)和塊之外傳輸控制,但永遠(yuǎn)不會(huì)轉(zhuǎn)移到塊中。

標(biāo)簽有自己的聲明空間,不會(huì)干擾其他標(biāo)識(shí)符。這個(gè)例子

1 int F(int x) { 2 if (x >= 0) goto x; 3 x = -x; 4 x: return x; 5 }

是有效的,并將名稱x用作參數(shù)和標(biāo)簽。

標(biāo)簽語(yǔ)句的執(zhí)行完全對(duì)應(yīng)于標(biāo)簽后面的語(yǔ)句的執(zhí)行。

除了正??刂屏魈峁┑目稍L問(wèn)性之外,如果標(biāo)簽由可訪問(wèn)goto語(yǔ)句引用,則可以訪問(wèn)帶標(biāo)簽的語(yǔ)句。(例外:如果goto語(yǔ)句位于try包含finally塊的內(nèi)部,并且?guī)?biāo)簽的語(yǔ)句在該區(qū)域之外try,并且該finally塊的結(jié)束點(diǎn)無(wú)法訪問(wèn),則無(wú)法從該goto語(yǔ)句訪問(wèn)帶標(biāo)簽的語(yǔ)句。)

聲明語(yǔ)句

一個(gè)declaration_statement聲明一個(gè)局部變量或常量。聲明語(yǔ)句在塊中是允許的,但不允許作為嵌入語(yǔ)句。

1 declaration_statement 2 : local_variable_declaration ';' 3 | local_constant_declaration ';' 4 ;

局部變量聲明

一個(gè)local_variable_declaration聲明一個(gè)或多個(gè)局部變量。

1 local_variable_declaration 2 : local_variable_type local_variable_declarators 3 ; 4 5 local_variable_type 6 : type 7 | 'var' 8 ; 9 10 local_variable_declarators 11 : local_variable_declarator 12 | local_variable_declarators ',' local_variable_declarator 13 ; 14 15 local_variable_declarator 16 : identifier 17 | identifier '=' local_variable_initializer 18 ; 19 20 local_variable_initializer 21 : expression 22 | array_initializer 23 | local_variable_initializer_unsafe 24 ;

所述local_variable_type一個(gè)的local_variable_declaration直接指定由該聲明引入的變量的類(lèi)型,或與該標(biāo)識(shí)符指示var該類(lèi)型應(yīng)該根據(jù)一個(gè)初始化來(lái)推斷。該類(lèi)型后跟一個(gè)local_variable_declarator列表,每個(gè)都引入一個(gè)新變量。甲local_variable_declarator由一個(gè)的標(biāo)識(shí)符名稱變量,任選地隨后通過(guò)“?=”令牌和local_variable_initializer,使該變量的初始值。

在局部變量聲明的上下文中,標(biāo)識(shí)符var充當(dāng)上下文關(guān)鍵字(關(guān)鍵字)。當(dāng)local_variable_type被指定為var并且沒(méi)有命名的類(lèi)型var在范圍內(nèi)時(shí),聲明是隱式類(lèi)型的局部變量聲明,其類(lèi)型是從關(guān)聯(lián)的初始化表達(dá)式的類(lèi)型。隱式類(lèi)型的局部變量聲明受以下限制:

  • 該local_variable_declaration不能包含多個(gè)local_variable_declarator秒。
  • 該local_variable_declarator必須包括local_variable_initializer。
  • 所述local_variable_initializer必須是表達(dá)。
  • 初始化表達(dá)式必須具有編譯時(shí)類(lèi)型。
  • 初始化表達(dá)式不能引用聲明的變量本身

以下是不正確的隱式類(lèi)型局部變量聲明的示例:

1 var x; // Error, no initializer to infer type from 2 var y = {1, 2, 3}; // Error, array initializer not permitted 3 var z = null; // Error, null does not have a type 4 var u = x => x + 1; // Error, anonymous functions do not have a type 5 var v = v++; // Error, initializer cannot refer to variable itself

使用simple_name(簡(jiǎn)單名稱)在表達(dá)式中獲取局部變量的值,并使用賦值(賦值運(yùn)算符)修改局部變量的值。必須在獲得其值的每個(gè)位置明確賦值(定義賦值)局部變量。

在local_variable_declaration中聲明的局部變量的范圍是聲明發(fā)生的塊。在局部變量的local_variable_declarator之前的文本位置引用局部變量是錯(cuò)誤的。在局部變量的范圍內(nèi),聲明另一個(gè)具有相同名稱的局部變量或常量是編譯時(shí)錯(cuò)誤。

聲明多個(gè)變量的局部變量聲明等效于具有相同類(lèi)型的單個(gè)變量的多個(gè)聲明。此外,局部變量聲明中的變量初始值設(shè)定項(xiàng)與聲明后立即插入的賦值語(yǔ)句完全對(duì)應(yīng)。

這個(gè)例子

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

完全對(duì)應(yīng)于

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

在隱式類(lèi)型的局部變量聲明中,聲明的局部變量的類(lèi)型與用于初始化變量的表達(dá)式的類(lèi)型相同。例如:

1 var i = 5; 2 var s = "Hello"; 3 var d = 1.0; 4 var numbers = new int[] {1, 2, 3}; 5 var orders = new Dictionary<int,Order>();

上面隱式類(lèi)型化的局部變量聲明與以下顯式類(lèi)型聲明完全等效:

1 int i = 5; 2 string s = "Hello"; 3 double d = 1.0; 4 int[] numbers = new int[] {1, 2, 3}; 5 Dictionary<int,Order> orders = new Dictionary<int,Order>();

局部常量聲明

一個(gè)local_constant_declaration聲明一個(gè)或多個(gè)局部常量。

1 local_constant_declaration 2 : 'const' type constant_declarators 3 ; 4 5 constant_declarators 6 : constant_declarator (',' constant_declarator)* 7 ; 8 9 constant_declarator 10 : identifier '=' constant_expression 11 ;

該類(lèi)型一的local_constant_declaration指定由該聲明引入的常數(shù)的類(lèi)型。該類(lèi)型后面是一個(gè)constant_declarator列表,每個(gè)都引入一個(gè)新的常量。甲constant_declarator由一個(gè)的標(biāo)識(shí)符名稱的恒定,接著是“?=”標(biāo)記,接著是constant_expression(常量表達(dá)式給出的常數(shù)的值)。

本地常量聲明的類(lèi)型和constant_expression必須遵循與常量成員聲明(常量)相同的規(guī)則。

使用simple_name(簡(jiǎn)單名稱)在表達(dá)式中獲取局部常量的值。

局部常量的范圍是聲明發(fā)生的塊。在constant_declarator之前的文本位置引用局部常量是錯(cuò)誤的。在局部常量的范圍內(nèi),聲明另一個(gè)具有相同名稱的局部變量或常量是編譯時(shí)錯(cuò)誤。

聲明多個(gè)常量的局部常量聲明等效于具有相同類(lèi)型的單個(gè)常量的多個(gè)聲明。

表達(dá)式語(yǔ)句

一個(gè)expression_statement計(jì)算所給定的表達(dá)。表達(dá)式計(jì)算的值(如果有)將被丟棄。

1 expression_statement 2 : statement_expression ';' 3 ; 4 5 statement_expression 6 : invocation_expression 7 | null_conditional_invocation_expression 8 | object_creation_expression 9 | assignment 10 | post_increment_expression 11 | post_decrement_expression 12 | pre_increment_expression 13 | pre_decrement_expression 14 | await_expression 15 ;

并非所有表達(dá)式都被允許作為語(yǔ)句。特別是,諸如x + y和x == 1僅僅計(jì)算一個(gè)值(將被丟棄)的表達(dá)式不允許作為語(yǔ)句。

執(zhí)行expression_statement會(huì)計(jì)算包含的表達(dá)式,然后將控制權(quán)轉(zhuǎn)移到expression_statement的結(jié)束點(diǎn)。如果可以訪問(wèn)expression_statement,則可以訪問(wèn)expression_statement的結(jié)束點(diǎn)。

Selection語(yǔ)句

Selection語(yǔ)句根據(jù)某個(gè)表達(dá)式的值選擇一些可能的語(yǔ)句來(lái)執(zhí)行。

1 selection_statement 2 : if_statement 3 | switch_statement 4 ;

if語(yǔ)句

該if語(yǔ)句根據(jù)布爾表達(dá)式的值選擇要執(zhí)行的語(yǔ)句。

1 if_statement 2 : 'if' '(' boolean_expression ')' embedded_statement 3 | 'if' '(' boolean_expression ')' embedded_statement 'else' embedded_statement 4 ;

一個(gè)else部分與詞法最近的前一個(gè)相關(guān)聯(lián)的if由該句法允許的。因此,if形式的陳述

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

相當(dāng)于

1 if (x) { 2 if (y) { 3 F(); 4 } 5 else { 6 G(); 7 } 8 }

一個(gè)if語(yǔ)句的執(zhí)行方式如下:

  • 所述邏輯表達(dá)式(布爾表達(dá)式)進(jìn)行評(píng)價(jià)。
  • 如果布爾表達(dá)式產(chǎn)生true,則控制轉(zhuǎn)移到第一個(gè)嵌入語(yǔ)句。當(dāng)控制到達(dá)該語(yǔ)句的結(jié)束點(diǎn)時(shí),控制權(quán)轉(zhuǎn)移到if語(yǔ)句的結(jié)束點(diǎn)。
  • 如果布爾表達(dá)式產(chǎn)生false并且如果存在else部件,則控制轉(zhuǎn)移到第二個(gè)嵌入語(yǔ)句。當(dāng)控制到達(dá)該語(yǔ)句的結(jié)束點(diǎn)時(shí),控制權(quán)轉(zhuǎn)移到if語(yǔ)句的結(jié)束點(diǎn)。
  • 如果布爾表達(dá)式產(chǎn)生false并且如果else部件不存在,則控制轉(zhuǎn)移到if語(yǔ)句的結(jié)束點(diǎn)。

if如果if語(yǔ)句可達(dá)且布爾表達(dá)式?jīng)]有常量值,則可以訪問(wèn)語(yǔ)句的第一個(gè)嵌入語(yǔ)句false。

if如果if語(yǔ)句可訪問(wèn)且布爾表達(dá)式不具有常量值,則語(yǔ)句的第二個(gè)嵌入語(yǔ)句(如果存在)是可到達(dá)的true。

一個(gè)的結(jié)束點(diǎn)if語(yǔ)句是可到達(dá)如果嵌入語(yǔ)句中至少一個(gè)的結(jié)束點(diǎn)是可到達(dá)。此外,如果語(yǔ)句可以訪問(wèn)且布爾表達(dá)式?jīng)]有常量值,則可以訪問(wèn)if沒(méi)有任何else部分的語(yǔ)句的結(jié)束點(diǎn)。iftrue

switch語(yǔ)句

switch語(yǔ)句選擇執(zhí)行一個(gè)語(yǔ)句列表,該列表具有與switch表達(dá)式的值相對(duì)應(yīng)的關(guān)聯(lián)開(kāi)關(guān)標(biāo)簽。

1 switch_statement 2 : 'switch' '(' expression ')' switch_block 3 ; 4 5 switch_block 6 : '{' switch_section* '}' 7 ; 8 9 switch_section 10 : switch_label+ statement_list 11 ; 12 13 switch_label 14 : 'case' constant_expression ':' 15 | 'default' ':' 16 ;

在switch_statement由關(guān)鍵字switch,隨后是括號(hào)表達(dá)式(稱為開(kāi)關(guān)表達(dá)),接著是switch_block。所述switch_block由零個(gè)或多個(gè)switch_section?S,在大括號(hào)。每個(gè)switch_section包含一個(gè)或多個(gè)switch_label,后跟一個(gè)statement_list(語(yǔ)句列表)。

該管理型?A的switch陳述,由開(kāi)關(guān)式成立。

  • 如果開(kāi)關(guān)表達(dá)式的類(lèi)型是sbyte,byte,short,ushort,int,uint,long,ulong,bool,char,string,或enum_type,或者如果它是對(duì)應(yīng)于這些類(lèi)型之一的空類(lèi)型,那么這就是的主導(dǎo)類(lèi)型switch的語(yǔ)句。
  • 否則,只有一個(gè)用戶定義的隱式轉(zhuǎn)換(用戶定義的轉(zhuǎn)換)必須從開(kāi)關(guān)表達(dá)式的類(lèi)型存在以下可能的主導(dǎo)類(lèi)型之一:sbyte,byte,short,ushort,int,uint,long,ulong,char,string,或,對(duì)應(yīng)于空類(lèi)型其中一種類(lèi)型。
  • 否則,如果不存在此類(lèi)隱式轉(zhuǎn)換,或者如果存在多個(gè)此類(lèi)隱式轉(zhuǎn)換,則會(huì)發(fā)生編譯時(shí)錯(cuò)誤。

每個(gè)case標(biāo)簽的常量表達(dá)式必須表示一個(gè)可隱式轉(zhuǎn)換的值(隱式轉(zhuǎn)換)到該switch語(yǔ)句的控制類(lèi)型。如果case同一switch語(yǔ)句中的兩個(gè)或多個(gè)標(biāo)簽指定相同的常量值,則會(huì)發(fā)生編譯時(shí)錯(cuò)誤。

defaultswitch語(yǔ)句中最多只能有一個(gè)標(biāo)簽。

一個(gè)switch語(yǔ)句的執(zhí)行過(guò)程如下:

  • 評(píng)估switch表達(dá)式并將其轉(zhuǎn)換為管理類(lèi)型。
  • 如果case同一switch語(yǔ)句中的標(biāo)簽中指定的常量之一等于switch表達(dá)式的值,則控制將轉(zhuǎn)移到匹配case標(biāo)簽后面的語(yǔ)句列表中。
  • 如果case同一switch語(yǔ)句中的標(biāo)簽中指定的常量都不等于switch表達(dá)式的值,并且如果存在default標(biāo)簽,則控制將轉(zhuǎn)移到default標(biāo)簽后面的語(yǔ)句列表中。
  • 如果case同一switch語(yǔ)句中的標(biāo)簽中指定的常量都不等于switch表達(dá)式的值,并且如果不存在default標(biāo)簽,則控制將轉(zhuǎn)移到switch語(yǔ)句的結(jié)束點(diǎn)。

如果可以訪問(wèn)switch部分的語(yǔ)句列表的結(jié)束點(diǎn),則會(huì)發(fā)生編譯時(shí)錯(cuò)誤。這被稱為“不通過(guò)”規(guī)則。這個(gè)例子

1 switch (i) { 2 case 0: 3 CaseZero(); 4 break; 5 case 1: 6 CaseOne(); 7 break; 8 default: 9 CaseOthers(); 10 break; 11 }

是有效的,因?yàn)闆](méi)有切換部分具有可到達(dá)的終點(diǎn)。與C和C ++不同,開(kāi)關(guān)部分的執(zhí)行不允許“通過(guò)”到下一個(gè)開(kāi)關(guān)部分和示例

1 switch (i) { 2 case 0: 3 CaseZero(); 4 case 1: 5 CaseZeroOrOne(); 6 default: 7 CaseAny(); 8 }

導(dǎo)致編譯時(shí)錯(cuò)誤。當(dāng)執(zhí)行交換機(jī)部分后執(zhí)行另一個(gè)交換機(jī)部分時(shí),必須使用顯式goto case或goto default語(yǔ)句:

1 switch (i) { 2 case 0: 3 CaseZero(); 4 goto case 1; 5 case 1: 6 CaseZeroOrOne(); 7 goto default; 8 default: 9 CaseAny(); 10 break; 11 }

switch_section中允許使用多個(gè)標(biāo)簽。這個(gè)例子

1 switch (i) { 2 case 0: 3 CaseZero(); 4 break; 5 case 1: 6 CaseOne(); 7 break; 8 case 2: 9 default: 10 CaseTwo(); 11 break; 12 }

已驗(yàn)證。該示例不“通過(guò)不落”的規(guī)則違反,因?yàn)闃?biāo)簽case 2:和default:是相同的部分switch_section。

“no fall through”規(guī)則可以防止在break語(yǔ)句被意外省略時(shí)出現(xiàn)在C和C ++中的常見(jiàn)錯(cuò)誤類(lèi)。此外,由于此規(guī)則,switch語(yǔ)句的切換部分可以任意重新排列,而不會(huì)影響語(yǔ)句的行為。例如,switch可以顛倒上述語(yǔ)句的各個(gè)部分,而不會(huì)影響語(yǔ)句的行為:

1 switch (i) { 2 default: 3 CaseAny(); 4 break; 5 case 1: 6 CaseZeroOrOne(); 7 goto default; 8 case 0: 9 CaseZero(); 10 goto case 1; 11 }

switch部分的語(yǔ)句列表通常以a?break,goto case或goto default語(yǔ)句結(jié)尾,但允許呈現(xiàn)語(yǔ)句列表的端點(diǎn)不可達(dá)的任何構(gòu)造。例如,已知while由布爾表達(dá)式控制的語(yǔ)句true永遠(yuǎn)不會(huì)到達(dá)其終點(diǎn)。同樣,throw或者return語(yǔ)句總是將控制轉(zhuǎn)移到其他地方并且永遠(yuǎn)不會(huì)到達(dá)其終點(diǎn)。因此,以下示例有效:

1 switch (i) { 2 case 0: 3 while (true) F(); 4 case 1: 5 throw new ArgumentException(); 6 case 2: 7 return; 8 }

switch聲明的管理類(lèi)型可以是類(lèi)型string。例如:

1 void DoCommand(string command) { 2 switch (command.ToLower()) { 3 case "run": 4 DoRun(); 5 break; 6 case "save": 7 DoSave(); 8 break; 9 case "quit": 10 DoQuit(); 11 break; 12 default: 13 InvalidCommand(command); 14 break; 15 } 16 }

與字符串相等運(yùn)算符(字符串相等運(yùn)算符)一樣,該switch語(yǔ)句區(qū)分大小寫(xiě),并且僅當(dāng)開(kāi)關(guān)表達(dá)式字符串與case標(biāo)簽常量完全匹配時(shí)才會(huì)執(zhí)行給定的開(kāi)關(guān)部分。

當(dāng)switch語(yǔ)句的控制類(lèi)型為時(shí)string,該值null被允許作為案例標(biāo)簽常量。

該STATEMENT_LIST一個(gè)第switch_block可以包含聲明語(yǔ)句(聲明語(yǔ)句)。在switch塊中聲明的局部變量或常量的范圍是switch塊。

如果switch語(yǔ)句可訪問(wèn)且至少滿足下列條件之一,則可以訪問(wèn)給定switch部分的語(yǔ)句列表:

  • switch表達(dá)式是一個(gè)非常量值。
  • switch表達(dá)式是一個(gè)與caseswitch部分中的標(biāo)簽匹配的常量值。
  • switch表達(dá)式是一個(gè)與任何case標(biāo)簽都不匹配的常量值,switch部分包含default標(biāo)簽。
  • 交換機(jī)部分的交換機(jī)標(biāo)簽由可達(dá)goto case或goto default語(yǔ)句引用。

switch如果至少滿足下列條件之一,則可以訪問(wèn)語(yǔ)句的結(jié)束點(diǎn):

  • 該switch語(yǔ)句包含break退出switch語(yǔ)句的可訪問(wèn)語(yǔ)句。
  • 該switch語(yǔ)句是可到達(dá)的,switch表達(dá)式是不恒定的值,并且沒(méi)有default標(biāo)簽存在。
  • 該switch語(yǔ)句是可訪問(wèn)的,switch表達(dá)式是一個(gè)與任何case標(biāo)簽都不匹配的常量值,并且不存在default標(biāo)簽。

迭代語(yǔ)句

迭代語(yǔ)句重復(fù)執(zhí)行嵌入語(yǔ)句。

1 iteration_statement 2 : while_statement 3 | do_statement 4 | for_statement 5 | foreach_statement 6 ;

while語(yǔ)句

該while語(yǔ)句有條件地執(zhí)行嵌入語(yǔ)句零次或多次。

1 while_statement 2 : 'while' '(' boolean_expression ')' embedded_statement 3 ;

一個(gè)while語(yǔ)句的執(zhí)行過(guò)程如下:

  • 所述邏輯表達(dá)式(布爾表達(dá)式)進(jìn)行評(píng)價(jià)。
  • 如果布爾表達(dá)式產(chǎn)生true,則控制轉(zhuǎn)移到嵌入語(yǔ)句。當(dāng)控制到達(dá)嵌入語(yǔ)句的結(jié)束點(diǎn)時(shí)(可能來(lái)自continue語(yǔ)句的執(zhí)行),控制轉(zhuǎn)移到while語(yǔ)句的開(kāi)頭。
  • 如果布爾表達(dá)式產(chǎn)生false,則控制轉(zhuǎn)移到while語(yǔ)句的結(jié)束點(diǎn)。

在語(yǔ)句的嵌入語(yǔ)句中while,break語(yǔ)句(break語(yǔ)句)可用于將控制轉(zhuǎn)移到while語(yǔ)句的結(jié)束點(diǎn)(從而結(jié)束嵌入語(yǔ)句的迭代),并且continue語(yǔ)句(continue語(yǔ)句)可用于將控制轉(zhuǎn)移到嵌入語(yǔ)句的結(jié)束點(diǎn)(從而執(zhí)行語(yǔ)句的另一次迭代while)。

while如果while語(yǔ)句可訪問(wèn)且布爾表達(dá)式?jīng)]有常量值,則可以訪問(wèn)語(yǔ)句的嵌入語(yǔ)句false。

while如果至少滿足下列條件之一,則可以訪問(wèn)語(yǔ)句的結(jié)束點(diǎn):

  • 該while語(yǔ)句包含break退出while語(yǔ)句的可訪問(wèn)語(yǔ)句。
  • 該while語(yǔ)句是可訪問(wèn)的,并且布爾表達(dá)式?jīng)]有常量值true。

do語(yǔ)句

該do語(yǔ)句有條件地執(zhí)行嵌入語(yǔ)句一次或多次。

1 do_statement 2 : 'do' embedded_statement 'while' '(' boolean_expression ')' ';' 3 ;

一個(gè)do語(yǔ)句的執(zhí)行過(guò)程如下:

  • 控制轉(zhuǎn)移到嵌入語(yǔ)句。
  • 當(dāng)控件到達(dá)嵌入語(yǔ)句的結(jié)束點(diǎn)時(shí)(可能來(lái)自continue語(yǔ)句的執(zhí)行),將評(píng)估boolean_expression(布爾表達(dá)式)。如果布爾表達(dá)式產(chǎn)生true,則控制轉(zhuǎn)移到do語(yǔ)句的開(kāi)頭。否則,控制轉(zhuǎn)移到do語(yǔ)句的結(jié)束點(diǎn)。

在語(yǔ)句的嵌入語(yǔ)句中do,break語(yǔ)句(break語(yǔ)句)可用于將控制轉(zhuǎn)移到do語(yǔ)句的結(jié)束點(diǎn)(從而結(jié)束嵌入語(yǔ)句的迭代),并且continue語(yǔ)句(continue語(yǔ)句)可用于將控制轉(zhuǎn)移到嵌入語(yǔ)句的結(jié)束點(diǎn)。

do如果do語(yǔ)句可訪問(wèn),則可以訪問(wèn)語(yǔ)句的嵌入語(yǔ)句。

do如果至少滿足下列條件之一,則可以訪問(wèn)語(yǔ)句的結(jié)束點(diǎn):

  • 該do語(yǔ)句包含break退出do語(yǔ)句的可訪問(wèn)語(yǔ)句。
  • 嵌入語(yǔ)句的結(jié)束點(diǎn)是可到達(dá)的,布爾表達(dá)式?jīng)]有常量值true。

for語(yǔ)句

該for語(yǔ)句評(píng)估一系列初始化表達(dá)式,然后在條件為真時(shí)重復(fù)執(zhí)行嵌入語(yǔ)句并計(jì)算迭代表達(dá)式序列。

1 for_statement 2 : 'for' '(' for_initializer? ';' for_condition? ';' for_iterator? ')' embedded_statement 3 ; 4 5 for_initializer 6 : local_variable_declaration 7 | statement_expression_list 8 ; 9 10 for_condition 11 : boolean_expression 12 ; 13 14 for_iterator 15 : statement_expression_list 16 ; 17 18 statement_expression_list 19 : statement_expression (',' statement_expression)* 20 ;

for_initializer,如果存在的話,由一個(gè)或者的local_variable_declaration(本地變量聲明)或列表statement_expression?S(表達(dá)式語(yǔ)句由逗號(hào)分隔)。由for_initializer聲明的局部變量的范圍從變量的local_variable_declarator開(kāi)始,并延伸到嵌入語(yǔ)句的末尾。范圍包括for_condition和for_iterator。

的for_condition,如果存在的話,必須是一個(gè)邏輯表達(dá)式(布爾表達(dá)式)。

的for_iterator,如果存在,包含的列表的statement_expression?S(表達(dá)式語(yǔ)句由逗號(hào)分隔)。

for語(yǔ)句執(zhí)行如下:

  • 如果存在for_initializer,則變量初始值設(shè)定項(xiàng)或語(yǔ)句表達(dá)式按其寫(xiě)入順序執(zhí)行。此步驟僅執(zhí)行一次。
  • 如果存在for_condition,則對(duì)其進(jìn)行評(píng)估。
  • 如果for_condition不存在或者評(píng)估結(jié)果true,則控制權(quán)轉(zhuǎn)移到嵌入語(yǔ)句。當(dāng)控件到達(dá)嵌入語(yǔ)句的結(jié)束點(diǎn)時(shí)(可能來(lái)自語(yǔ)句的執(zhí)行continue),for_iterator的表達(dá)式(如果有的話)按順序計(jì)算,然后執(zhí)行另一次迭代,從評(píng)估for_condition開(kāi)始。上面的步驟。
  • 如果存在for_condition并且評(píng)估結(jié)果false,則控制轉(zhuǎn)移到for語(yǔ)句的結(jié)束點(diǎn)。

在語(yǔ)句的嵌入語(yǔ)句中for,break語(yǔ)句(break語(yǔ)句)可用于將控制轉(zhuǎn)移到for語(yǔ)句的結(jié)束點(diǎn)(從而結(jié)束嵌入語(yǔ)句的迭代),并且continue語(yǔ)句(continue語(yǔ)句)可用于將控制轉(zhuǎn)移到嵌入語(yǔ)句的結(jié)束點(diǎn)(從而執(zhí)行for_iterator并執(zhí)行for語(yǔ)句的另一次迭代,從for_condition開(kāi)始)。

for如果滿足下列條件之一,則可以訪問(wèn)語(yǔ)句的嵌入語(yǔ)句:

  • 該for語(yǔ)句是可訪問(wèn)的,并且不存在for_condition。
  • 該for語(yǔ)句是可訪問(wèn)的,并且存在for_condition并且沒(méi)有常量值false。

for如果至少滿足下列條件之一,則可以訪問(wèn)語(yǔ)句的結(jié)束點(diǎn):

  • 該for語(yǔ)句包含break退出for語(yǔ)句的可訪問(wèn)語(yǔ)句。
  • 該for語(yǔ)句是可訪問(wèn)的,并且存在for_condition并且沒(méi)有常量值true。

foreach語(yǔ)句

該foreach語(yǔ)句枚舉集合的元素,為集合的每個(gè)元素執(zhí)行嵌入式語(yǔ)句。

1 foreach_statement 2 : 'foreach' '(' local_variable_type identifier 'in' expression ')' embedded_statement 3 ;

的類(lèi)型和標(biāo)識(shí)符一個(gè)的foreach聲明聲明迭代變量的聲明。如果var標(biāo)識(shí)符作為local_variable_type給出,并且沒(méi)有命名的類(lèi)型var在范圍內(nèi),則迭代變量被稱為隱式類(lèi)型的迭代變量,并且其類(lèi)型被視為foreach語(yǔ)句的元素類(lèi)型,如下所述。迭代變量對(duì)應(yīng)于只讀局部變量,其范圍擴(kuò)展到嵌入語(yǔ)句。執(zhí)行期間foreach聲明,迭代變量表示當(dāng)前正在執(zhí)行迭代的集合元素。如果嵌入語(yǔ)句試圖修改迭代變量(通過(guò)賦值或發(fā)生編譯時(shí)間錯(cuò)誤++和--操作員)或通過(guò)迭代變量作為ref或out參數(shù)。

在下文中,為了簡(jiǎn)潔,IEnumerable,IEnumerator,IEnumerable<T>和IEnumerator<T>指的是命名空間的相應(yīng)類(lèi)型System.Collections和System.Collections.Generic。

foreach語(yǔ)句的編譯時(shí)處理首先確定表達(dá)式的集合類(lèi)型,枚舉器類(lèi)型和元素類(lèi)型。該決定如下:

  • 如果類(lèi)型X的表達(dá)是一個(gè)數(shù)組類(lèi)型,那么存在來(lái)自隱式引用轉(zhuǎn)換X到IEnumerable接口(因?yàn)镾ystem.Array實(shí)現(xiàn)該接口)。的集合類(lèi)型是IEnumerable接口,該枚舉類(lèi)型是IEnumerator接口和元素類(lèi)型是陣列類(lèi)型的元素類(lèi)型X。
  • 如果類(lèi)型X的表達(dá)是dynamic則存在從隱式轉(zhuǎn)換表達(dá)式的IEnumerable接口(隱式動(dòng)態(tài)轉(zhuǎn)換)。該集合類(lèi)型是IEnumerable接口和枚舉類(lèi)型是IEnumerator接口。如果var標(biāo)識(shí)符是local_variable_type,那么元素類(lèi)型是dynamic,否則它是object。
  • 否則,確定類(lèi)型X是否具有適當(dāng)?shù)腉etEnumerator方法:

    • 對(duì)X具有標(biāo)識(shí)符GetEnumerator且沒(méi)有類(lèi)型參數(shù)的類(lèi)型執(zhí)行成員查找。如果成員查找不產(chǎn)生匹配,或者產(chǎn)生歧義,或產(chǎn)生不是方法組的匹配,請(qǐng)檢查可枚舉接口,如下所述。如果成員查找產(chǎn)生除方法組或不匹配之外的任何內(nèi)容,建議發(fā)出警告。
    • 使用生成的方法組和空參數(shù)列表執(zhí)行重載解析。如果重載決策導(dǎo)致沒(méi)有適用的方法,導(dǎo)致歧義,或?qū)е聠蝹€(gè)最佳方法但該方法是靜態(tài)的或不公開(kāi)的,請(qǐng)檢查可枚舉的接口,如下所述。如果重載決策產(chǎn)生除明確的公共實(shí)例方法或沒(méi)有適用的方法之外的任何內(nèi)容,建議發(fā)出警告。
    • 如果返回類(lèi)型E的的GetEnumerator方法不是類(lèi),結(jié)構(gòu)或接口類(lèi)型,則產(chǎn)生一個(gè)錯(cuò)誤,并且不采取進(jìn)一步的步驟。
    • E使用標(biāo)識(shí)符執(zhí)行成員查找Current,不使用類(lèi)型參數(shù)。如果成員查找不產(chǎn)生匹配,則結(jié)果是錯(cuò)誤,或者結(jié)果是除允許讀取的公共實(shí)例屬性之外的任何內(nèi)容,產(chǎn)生錯(cuò)誤并且不執(zhí)行進(jìn)一步的步驟。
    • E使用標(biāo)識(shí)符執(zhí)行成員查找MoveNext,不使用類(lèi)型參數(shù)。如果成員查找不產(chǎn)生匹配,則結(jié)果是錯(cuò)誤,或者結(jié)果是除方法組之外的任何內(nèi)容,產(chǎn)生錯(cuò)誤并且不執(zhí)行進(jìn)一步的步驟。
    • 使用空參數(shù)列表對(duì)方法組執(zhí)行重載分辨率。如果重載決策導(dǎo)致沒(méi)有適用的方法,導(dǎo)致歧義,或?qū)е聠蝹€(gè)最佳方法但該方法是靜態(tài)的或不公開(kāi)的,或者其返回類(lèi)型不是bool,則產(chǎn)生錯(cuò)誤并且不采取進(jìn)一步的步驟。
    • 的集合類(lèi)型是X,該枚舉類(lèi)型是E,和元素類(lèi)型是類(lèi)型Current屬性。
  • 否則,檢查可枚舉的接口:

    • 如果所有的類(lèi)型中Ti對(duì)于其存在從隱式轉(zhuǎn)換X到IEnumerable<Ti>,有一種獨(dú)特類(lèi)型T,使得T不dynamic和所有其他Ti有從隱式轉(zhuǎn)換IEnumerable<T>到IEnumerable<Ti>,則該集合類(lèi)型是接口IEnumerable<T>,該枚舉類(lèi)型是接口IEnumerator<T>,元素類(lèi)型是T。
    • 否則,如果存在多個(gè)這樣的類(lèi)型T,則產(chǎn)生錯(cuò)誤并且不采取進(jìn)一步的步驟。
    • 否則,如果存在的隱式轉(zhuǎn)換從X到System.Collections.IEnumerable接口,則集合類(lèi)型是這樣的接口,所述枚舉類(lèi)型是接口System.Collections.IEnumerator,并且元素類(lèi)型是object。
    • 否則,將產(chǎn)生錯(cuò)誤,并且不會(huì)采取進(jìn)一步的步驟。

上述步驟如果成功,則明確地生成集合類(lèi)型C,枚舉器類(lèi)型E和元素類(lèi)型T。表格的foreach聲明

foreach (V v in x) embedded_statement

然后擴(kuò)展到:

1 { 2 E e = ((C)(x)).GetEnumerator(); 3 try { 4 while (e.MoveNext()) { 5 V v = (V)(T)e.Current; 6 embedded_statement 7 } 8 } 9 finally { 10 ... // Dispose e 11 } 12 }

變量e對(duì)表達(dá)式x或嵌入語(yǔ)句或程序的任何其他源代碼不可見(jiàn)或不可訪問(wèn)。該變量v在嵌入語(yǔ)句中是只讀的。如果沒(méi)有從(元素類(lèi)型)到(foreach語(yǔ)句中的local_variable_type)的顯式轉(zhuǎn)換(顯式轉(zhuǎn)換),則會(huì)產(chǎn)生錯(cuò)誤,并且不會(huì)采取進(jìn)一步的步驟。如果有值,則在運(yùn)行時(shí)拋出a?。TVxnullSystem.NullReferenceException

允許實(shí)現(xiàn)以不同方式實(shí)現(xiàn)給定的foreach語(yǔ)句,例如出于性能原因,只要行為與上述擴(kuò)展一致即可。

vwhile循環(huán)內(nèi)部的位置對(duì)于embedded_statement中發(fā)生的任何匿名函數(shù)如何捕獲它非常重要。

例如:

1 int[] values = { 7, 9, 13 }; 2 Action f = null; 3 4 foreach (var value in values) 5 { 6 if (f == null) f = () => Console.WriteLine("First value: " + value); 7 } 8 9 f();

如果v在while循環(huán)之外聲明,它將在所有迭代之間共享,并且它在for循環(huán)之后的值將是最終值13,這f將是打印的調(diào)用。相反,因?yàn)槊看蔚加凶约旱淖兞縱,f在第一次迭代中捕獲的變量將繼續(xù)保持值7,即將打印的值。(注意:早期版本的C#v在while循環(huán)之外聲明。)

finally塊的主體按照以下步驟構(gòu)造:

  • 如果存在從一個(gè)隱式轉(zhuǎn)換E到System.IDisposable接口,則

    • 如果E是非可空值類(lèi)型,則finally子句將擴(kuò)展為語(yǔ)義等效于:

    • 1 finally { 2 ((System.IDisposable)e).Dispose(); 3 }
    • ?否則,finally子句將擴(kuò)展為語(yǔ)義等效于:
    • 1 finally { 2 if (e != null) ((System.IDisposable)e).Dispose(); 3 }

      除了if?E是值類(lèi)型,或?qū)嵗癁橹殿?lèi)型的類(lèi)型參數(shù)之外,to的強(qiáng)制e轉(zhuǎn)換System.IDisposable不會(huì)導(dǎo)致裝箱發(fā)生。

  • 否則,如果E是密封類(lèi)型,則finally子句將擴(kuò)展為空塊:

1 finally { 2 }
  • 否則,finally子句擴(kuò)展為:

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

d任何用戶代碼都看不到或訪問(wèn)本地變量。特別是,它不會(huì)與其范圍包含finally塊的任何其他變量沖突。

foreach遍歷數(shù)組元素的順序如下:對(duì)于單維數(shù)組,元素以遞增的索引順序遍歷,從索引開(kāi)始,以索引0結(jié)束Length - 1。對(duì)于多維數(shù)組,遍歷元素,使得最右邊的維度的索引首先增加,然后是下一個(gè)左維度,依此類(lèi)推到左邊。

以下示例按元素順序打印出二維數(shù)組中的每個(gè)值:

1 using System; 2 3 class Test 4 { 5 static void Main() { 6 double[,] values = { 7 {1.2, 2.3, 3.4, 4.5}, 8 {5.6, 6.7, 7.8, 8.9} 9 }; 10 11 foreach (double elementValue in values) 12 Console.Write("{0} ", elementValue); 13 14 Console.WriteLine(); 15 } 16 }

產(chǎn)生的產(chǎn)出如下:

1.2 2.3 3.4 4.5 5.6 6.7 7.8 8.9

在這個(gè)例子中

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

n推斷的類(lèi)型是int,元素類(lèi)型numbers。

跳轉(zhuǎn)語(yǔ)句

跳轉(zhuǎn)語(yǔ)句無(wú)條件地轉(zhuǎn)移控制。

1 jump_statement 2 : break_statement 3 | continue_statement 4 | goto_statement 5 | return_statement 6 | throw_statement 7 ;

跳轉(zhuǎn)語(yǔ)句轉(zhuǎn)移控制的位置稱為跳轉(zhuǎn)語(yǔ)句的目標(biāo)。

當(dāng)一個(gè)塊內(nèi)發(fā)生跳轉(zhuǎn)語(yǔ)句,并且該跳轉(zhuǎn)語(yǔ)句的目標(biāo)位于該塊之外時(shí),跳轉(zhuǎn)語(yǔ)句被稱為退出該塊。雖然跳轉(zhuǎn)語(yǔ)句可以將控制轉(zhuǎn)移出塊,但它永遠(yuǎn)不會(huì)將控制轉(zhuǎn)移到塊中。

由于存在干預(yù)try語(yǔ)句,跳轉(zhuǎn)語(yǔ)句的執(zhí)行變得復(fù)雜。在沒(méi)有這樣的try語(yǔ)句的情況下,跳轉(zhuǎn)語(yǔ)句無(wú)條件地將控制從跳轉(zhuǎn)語(yǔ)句轉(zhuǎn)移到其目標(biāo)。在存在這樣的干預(yù)try陳述的情況下,執(zhí)行更加復(fù)雜。如果跳轉(zhuǎn)語(yǔ)句退出try具有關(guān)聯(lián)finally塊的一個(gè)或多個(gè)塊,則控制最初被轉(zhuǎn)移到finally最內(nèi)層try語(yǔ)句的塊。當(dāng)控制到達(dá)finally塊的結(jié)束點(diǎn)時(shí),控制轉(zhuǎn)移到finally下一個(gè)封閉try語(yǔ)句的塊。重復(fù)該過(guò)程,直到執(zhí)行finally了所有干預(yù)try語(yǔ)句的塊。

在這個(gè)例子中

1 using System; 2 3 class Test 4 { 5 static void Main() { 6 while (true) { 7 try { 8 try { 9 Console.WriteLine("Before break"); 10 break; 11 } 12 finally { 13 Console.WriteLine("Innermost finally block"); 14 } 15 } 16 finally { 17 Console.WriteLine("Outermost finally block"); 18 } 19 } 20 Console.WriteLine("After break"); 21 } 22 }

在將控制轉(zhuǎn)移到跳轉(zhuǎn)語(yǔ)句的目標(biāo)之前,執(zhí)行finally與兩個(gè)try語(yǔ)句關(guān)聯(lián)的塊。

產(chǎn)生的產(chǎn)出如下:

1 Before break 2 Innermost finally block 3 Outermost finally block 4 After break

break語(yǔ)句

該break語(yǔ)句退出直接封閉switch,while,do,for,或foreach語(yǔ)句。

1 break_statement 2 : 'break' ';' 3 ;

一個(gè)目標(biāo)break的語(yǔ)句是最近的封閉的結(jié)束點(diǎn)switch,while,do,for,或foreach語(yǔ)句。如果break語(yǔ)句不是由一個(gè)封閉的switch,while,do,for,或foreach語(yǔ)句,將發(fā)生編譯時(shí)錯(cuò)誤。

當(dāng)多個(gè)switch,while,do,for,或foreach語(yǔ)句相互嵌套,一個(gè)break聲明僅適用于最里面的語(yǔ)句。要跨多個(gè)嵌套級(jí)別傳輸控制,必須使用goto語(yǔ)句(goto語(yǔ)句)。

一個(gè)break語(yǔ)句不能退出一個(gè)finally塊(try語(yǔ)句)。當(dāng)一個(gè)break語(yǔ)句出現(xiàn)在一個(gè)finally塊中時(shí),該break語(yǔ)句的目標(biāo)必須在同一個(gè)finally塊內(nèi);?否則,發(fā)生編譯時(shí)錯(cuò)誤。

一個(gè)break語(yǔ)句的執(zhí)行過(guò)程如下:

  • 如果break語(yǔ)句退出try具有關(guān)聯(lián)finally塊的一個(gè)或多個(gè)塊,則控制最初被轉(zhuǎn)移到finally最內(nèi)層try語(yǔ)句的塊。當(dāng)控制到達(dá)finally塊的結(jié)束點(diǎn)時(shí),控制轉(zhuǎn)移到finally下一個(gè)封閉try語(yǔ)句的塊。重復(fù)該過(guò)程,直到執(zhí)行finally了所有干預(yù)try語(yǔ)句的塊。
  • 控制權(quán)轉(zhuǎn)移到break聲明的目標(biāo)。

因?yàn)閎reak語(yǔ)句無(wú)條件地將控制權(quán)轉(zhuǎn)移到其他地方,所以break語(yǔ)句的終點(diǎn)永遠(yuǎn)不可達(dá)。

continue語(yǔ)句

該continue語(yǔ)句開(kāi)始直接封閉的一個(gè)新的迭代while,do,for,或foreach語(yǔ)句。

1 continue_statement 2 : 'continue' ';' 3 ;

一個(gè)目標(biāo)continue的語(yǔ)句是最近的封閉的嵌入語(yǔ)句的結(jié)束點(diǎn)while,do,for,或foreach語(yǔ)句。如果continue語(yǔ)句不是由一個(gè)封閉的while,do,for,或foreach語(yǔ)句,將發(fā)生編譯時(shí)錯(cuò)誤。

當(dāng)多個(gè)while,do,for,或foreach語(yǔ)句相互嵌套,一個(gè)continue聲明僅適用于最里面的語(yǔ)句。要跨多個(gè)嵌套級(jí)別傳輸控制,必須使用goto語(yǔ)句(goto語(yǔ)句)。

一個(gè)continue語(yǔ)句不能退出一個(gè)finally塊(try語(yǔ)句)。當(dāng)一個(gè)continue語(yǔ)句出現(xiàn)在一個(gè)finally塊中時(shí),該continue語(yǔ)句的目標(biāo)必須在同一個(gè)finally塊內(nèi);?否則會(huì)發(fā)生編譯時(shí)錯(cuò)誤。

一個(gè)continue語(yǔ)句的執(zhí)行過(guò)程如下:

  • 如果continue語(yǔ)句退出try具有關(guān)聯(lián)finally塊的一個(gè)或多個(gè)塊,則控制最初被轉(zhuǎn)移到finally最內(nèi)層try語(yǔ)句的塊。當(dāng)控制到達(dá)finally塊的結(jié)束點(diǎn)時(shí),控制轉(zhuǎn)移到finally下一個(gè)封閉try語(yǔ)句的塊。重復(fù)該過(guò)程,直到執(zhí)行finally了所有干預(yù)try語(yǔ)句的塊。
  • 控制權(quán)轉(zhuǎn)移到continue聲明的目標(biāo)。

因?yàn)閏ontinue語(yǔ)句無(wú)條件地將控制權(quán)轉(zhuǎn)移到其他地方,所以continue語(yǔ)句的終點(diǎn)永遠(yuǎn)不可達(dá)。

goto語(yǔ)句

該goto語(yǔ)句將控制轉(zhuǎn)移到由標(biāo)簽標(biāo)記的語(yǔ)句。

1 goto_statement 2 : 'goto' identifier ';' 3 | 'goto' 'case' constant_expression ';' 4 | 'goto' 'default' ';' 5 ;

goto?標(biāo)識(shí)符語(yǔ)句的目標(biāo)是帶有給定標(biāo)簽的帶標(biāo)簽語(yǔ)句。如果當(dāng)前函數(shù)成員中不存在具有給定名稱的標(biāo)簽,或者該goto語(yǔ)句不在標(biāo)簽的范圍內(nèi),則會(huì)發(fā)生編譯時(shí)錯(cuò)誤。此規(guī)則允許使用goto語(yǔ)句將控制權(quán)移出嵌套作用域,但不能轉(zhuǎn)移到嵌套作用域中。在這個(gè)例子中

1 using System; 2 3 class Test 4 { 5 static void Main(string[] args) { 6 string[,] table = { 7 {"Red", "Blue", "Green"}, 8 {"Monday", "Wednesday", "Friday"} 9 }; 10 11 foreach (string str in args) { 12 int row, colm; 13 for (row = 0; row <= 1; ++row) 14 for (colm = 0; colm <= 2; ++colm) 15 if (str == table[row,colm]) 16 goto done; 17 18 Console.WriteLine("{0} not found", str); 19 continue; 20 done: 21 Console.WriteLine("Found {0} at [{1}][{2}]", str, row, colm); 22 } 23 } 24 }

一個(gè)goto語(yǔ)句是用來(lái)傳輸控制出嵌套范圍。

goto case語(yǔ)句的目標(biāo)是直接封閉switch語(yǔ)句(switch語(yǔ)句)中的語(yǔ)句列表,其中包含case具有給定常量值的標(biāo)簽。如果goto case語(yǔ)句沒(méi)有被switch語(yǔ)句包含,如果constant_expression不能隱式轉(zhuǎn)換(隱式轉(zhuǎn)換)到最近的封閉switch語(yǔ)句的控制類(lèi)型,或者如果最近的封閉switch語(yǔ)句不包含case具有給定常量值的標(biāo)簽,則編譯發(fā)生時(shí)間錯(cuò)誤。

goto default語(yǔ)句的目標(biāo)是直接包含switch語(yǔ)句(switch語(yǔ)句)中的語(yǔ)句列表,其中包含default標(biāo)簽。如果goto default語(yǔ)句未包含在switch語(yǔ)句中,或者最近的封閉switch語(yǔ)句不包含default標(biāo)簽,則會(huì)發(fā)生編譯時(shí)錯(cuò)誤。

一個(gè)goto語(yǔ)句不能退出一個(gè)finally塊(try語(yǔ)句)。當(dāng)goto語(yǔ)句在finally塊中發(fā)生時(shí),goto語(yǔ)句的目標(biāo)必須在同一個(gè)finally塊內(nèi),否則會(huì)發(fā)生編譯時(shí)錯(cuò)誤。

一個(gè)goto語(yǔ)句的執(zhí)行過(guò)程如下:

  • 如果goto語(yǔ)句退出try具有關(guān)聯(lián)finally塊的一個(gè)或多個(gè)塊,則控制最初被轉(zhuǎn)移到finally最內(nèi)層try語(yǔ)句的塊。當(dāng)控制到達(dá)finally塊的結(jié)束點(diǎn)時(shí),控制轉(zhuǎn)移到finally下一個(gè)封閉try語(yǔ)句的塊。重復(fù)該過(guò)程,直到執(zhí)行finally了所有干預(yù)try語(yǔ)句的塊。
  • 控制權(quán)轉(zhuǎn)移到goto聲明的目標(biāo)。

因?yàn)間oto語(yǔ)句無(wú)條件地將控制權(quán)轉(zhuǎn)移到其他地方,所以goto語(yǔ)句的終點(diǎn)永遠(yuǎn)不可達(dá)。

return語(yǔ)句

該return語(yǔ)句將控制權(quán)返回給return語(yǔ)句出現(xiàn)的函數(shù)的當(dāng)前調(diào)用者。

1 return_statement 2 : 'return' expression? ';' 3 ;

return不帶表達(dá)式語(yǔ)句可用于僅在一個(gè)功能部件,其不計(jì)算的值,即,與結(jié)果類(lèi)型的方法(方法體)void,所述set屬性或索引的訪問(wèn),所述add與remove事件的存取器,一個(gè)實(shí)例構(gòu)造函數(shù),靜態(tài)構(gòu)造函數(shù)或析構(gòu)函數(shù)。

return具有表達(dá)式的語(yǔ)句只能在計(jì)算值的函數(shù)成員中使用,即具有非void結(jié)果類(lèi)型的方法,get屬性或索引器的訪問(wèn)者或用戶定義的運(yùn)算符。隱式轉(zhuǎn)換(隱式轉(zhuǎn)換)必須存在,從表達(dá)式的類(lèi)型到包含函數(shù)成員的返回類(lèi)型。

返回語(yǔ)句也可以在匿名函數(shù)表達(dá)式(匿名函數(shù)表達(dá)式)的主體中使用,并參與確定這些函數(shù)存在哪些轉(zhuǎn)換。

return語(yǔ)句出現(xiàn)在finally塊(try語(yǔ)句)中是編譯時(shí)錯(cuò)誤。

一個(gè)return語(yǔ)句的執(zhí)行過(guò)程如下:

  • 如果return語(yǔ)句指定了表達(dá)式,則計(jì)算表達(dá)式,并通過(guò)隱式轉(zhuǎn)換將結(jié)果值轉(zhuǎn)換為包含函數(shù)的返回類(lèi)型。轉(zhuǎn)換的結(jié)果成為函數(shù)產(chǎn)生的結(jié)果值。
  • 如果return語(yǔ)句被一個(gè)或多個(gè)try或catch帶有關(guān)聯(lián)finally塊的塊包圍,則控制最初被轉(zhuǎn)移到finally最內(nèi)層try語(yǔ)句的塊。當(dāng)控制到達(dá)finally塊的結(jié)束點(diǎn)時(shí),控制轉(zhuǎn)移到finally下一個(gè)封閉try語(yǔ)句的塊。重復(fù)此過(guò)程,直到執(zhí)行finally了所有封閉try語(yǔ)句的塊。
  • 如果包含函數(shù)不是異步函數(shù),則控制將返回包含函數(shù)的調(diào)用者以及結(jié)果值(如果有)。
  • 如果包含函數(shù)是異步函數(shù),則控制將返回到當(dāng)前調(diào)用者,并且結(jié)果值(如果有)將記錄在返回任務(wù)中,如(枚舉器接口)中所述。

因?yàn)閞eturn語(yǔ)句無(wú)條件地將控制權(quán)轉(zhuǎn)移到其他地方,所以return語(yǔ)句的終點(diǎn)永遠(yuǎn)不可達(dá)。

throw語(yǔ)句

該throw語(yǔ)句拋出異常。

1 throw_statement 2 : 'throw' expression? ';' 3 ;

throw帶有表達(dá)式的語(yǔ)句會(huì)拋出通過(guò)計(jì)算表達(dá)式生成的值。表達(dá)式必須表示類(lèi)類(lèi)型的值,該類(lèi)類(lèi)型System.Exception的類(lèi)類(lèi)型派生自System.Exception或具有System.Exception(或其子類(lèi))作為其有效基類(lèi)的類(lèi)型參數(shù)類(lèi)型。如果表達(dá)式的評(píng)估產(chǎn)生null,System.NullReferenceException則拋出a?。

throw沒(méi)有表達(dá)式的語(yǔ)句只能在catch塊中使用,在這種情況下,該語(yǔ)句會(huì)重新拋出該catch塊當(dāng)前正在處理的異常。

因?yàn)閠hrow語(yǔ)句無(wú)條件地將控制權(quán)轉(zhuǎn)移到其他地方,所以throw語(yǔ)句的終點(diǎn)永遠(yuǎn)不可達(dá)。

拋出異常時(shí),控制權(quán)轉(zhuǎn)移到可以處理異常catch的封閉try語(yǔ)句中的第一個(gè)子句。從拋出異常點(diǎn)到將控制轉(zhuǎn)移到合適的異常處理程序的過(guò)程發(fā)生的過(guò)程稱為異常傳播。異常的傳播包括重復(fù)評(píng)估以下步驟,直到catch找到與異常匹配的子句。在本說(shuō)明書(shū)中,拋出點(diǎn)最初是拋出異常的位置。

  • 在當(dāng)前函數(shù)成員中,try將檢查包含拋出點(diǎn)的每個(gè)語(yǔ)句。對(duì)于每個(gè)語(yǔ)句S,從最內(nèi)層try語(yǔ)句開(kāi)始到以最外層try語(yǔ)句結(jié)束,將評(píng)估以下步驟:

    • 如果try塊S包含拋出點(diǎn)并且如果S有一個(gè)或多個(gè)catch子句,則catch根據(jù)出現(xiàn)的順序檢查子句,以根據(jù)try語(yǔ)句一節(jié)中指定的規(guī)則找到異常的合適處理程序。如果找到匹配catch子句,則通過(guò)將控制轉(zhuǎn)移到該catch子句的塊來(lái)完成異常傳播。

    • 否則,如果try塊或catch塊S包圍拋出點(diǎn)并且如果S有finally塊,則控制轉(zhuǎn)移到finally塊。如果finally塊拋出另一個(gè)異常,則終止當(dāng)前異常的處理。否則,當(dāng)控制到達(dá)finally塊的結(jié)束點(diǎn)時(shí),繼續(xù)處理當(dāng)前異常。

  • 如果當(dāng)前函數(shù)調(diào)用中未找到異常處理程序,則終止函數(shù)調(diào)用,并發(fā)生以下任一情況:

    • 如果當(dāng)前函數(shù)是非異步的,則對(duì)函數(shù)的調(diào)用者重復(fù)上述步驟,其拋出點(diǎn)對(duì)應(yīng)于調(diào)用函數(shù)成員的語(yǔ)句。

    • 如果當(dāng)前函數(shù)是異步和任務(wù)返回,則異常將記錄在返回任務(wù)中,該任務(wù)將進(jìn)入故障或取消狀態(tài),如枚舉器接口中所述。

    • 如果當(dāng)前函數(shù)是async和void-returns,則會(huì)按照Enumerable接口中的描述通知當(dāng)前線程的同步上下文。

  • 如果異常處理終止當(dāng)前線程中的所有函數(shù)成員調(diào)用,指示該線程沒(méi)有該異常的處理程序,則該線程本身終止。這種終止的影響是實(shí)現(xiàn)定義的。

try語(yǔ)句

該try語(yǔ)句提供了一種機(jī)制,用于捕獲在執(zhí)行塊期間發(fā)生的異常。此外,該try語(yǔ)句還提供了指定在控制離開(kāi)try語(yǔ)句時(shí)始終執(zhí)行的代碼塊的功能。

1 try_statement 2 : 'try' block catch_clause+ 3 | 'try' block finally_clause 4 | 'try' block catch_clause+ finally_clause 5 ; 6 7 catch_clause 8 : 'catch' exception_specifier? exception_filter? block 9 ; 10 11 exception_specifier 12 : '(' type identifier? ')' 13 ; 14 15 exception_filter 16 : 'when' '(' expression ')' 17 ; 18 19 finally_clause 20 : 'finally' block 21 ;

有三種可能的try陳述形式:

  • 一個(gè)try塊后跟一個(gè)或多個(gè)catch塊。
  • 一個(gè)try塊然后是一個(gè)finally塊。
  • 一個(gè)try塊后跟一個(gè)或多個(gè)catch塊,后跟一個(gè)finally塊。

當(dāng)catch子句指定exception_specifier時(shí),類(lèi)型必須是System.Exception,派生自System.Exception的類(lèi)型System.Exception或具有(或其子類(lèi))作為其有效基類(lèi)的類(lèi)型參數(shù)類(lèi)型。

當(dāng)catch子句指定兩者exception_specifier與標(biāo)識(shí)符,一個(gè)異常變量給定名稱和類(lèi)型的聲明。異常變量對(duì)應(yīng)于局部變量,其范圍擴(kuò)展到catch子句。在執(zhí)行exception_filter和block期間,異常變量表示當(dāng)前正在處理的異常。出于明確賦值檢查的目的,異常變量在其整個(gè)范圍內(nèi)被認(rèn)為是明確賦值的。

除非catch子句包含異常變量名稱,否則無(wú)法訪問(wèn)過(guò)濾器和catch塊中的異常對(duì)象。

一個(gè)catch不指定條款exception_specifier被稱為一般catch條款。

一些編程語(yǔ)言可能支持不能表示為從中派生的對(duì)象的System.Exception異常,盡管這些異常永遠(yuǎn)不會(huì)由C#代碼生成。一般catch條款可用于捕獲此類(lèi)例外。因此,一般catch子句在語(yǔ)義上與指定類(lèi)型的子句不同System.Exception,因?yàn)榍罢咭部梢圆东@來(lái)自其他語(yǔ)言的異常。

為了找到異常的處理程序,catch以詞法順序檢查子句。如果catch子句指定了類(lèi)型但沒(méi)有異常過(guò)濾器,則catch同一try語(yǔ)句中的后一個(gè)子句的編譯時(shí)錯(cuò)誤是指定與該類(lèi)型相同或派生的類(lèi)型。如果catch子句指定沒(méi)有類(lèi)型且沒(méi)有指定過(guò)濾器,則它必須是該語(yǔ)句的最后一個(gè)catch子句try。

在catch塊中,沒(méi)有表達(dá)式的throw語(yǔ)句(throw語(yǔ)句)可用于重新拋出catch塊捕獲的異常。對(duì)異常變量的賦值不會(huì)改變重新拋出的異常。

在這個(gè)例子中

1 using System; 2 3 class Test 4 { 5 static void F() { 6 try { 7 G(); 8 } 9 catch (Exception e) { 10 Console.WriteLine("Exception in F: " + e.Message); 11 e = new Exception("F"); 12 throw; // re-throw 13 } 14 } 15 16 static void G() { 17 throw new Exception("G"); 18 } 19 20 static void Main() { 21 try { 22 F(); 23 } 24 catch (Exception e) { 25 Console.WriteLine("Exception in Main: " + e.Message); 26 } 27 } 28 }

該方法F捕獲異常,將一些診斷信息寫(xiě)入控制臺(tái),更改異常變量,并重新拋出異常。重新拋出的異常是原始異常,因此產(chǎn)生的輸出是:

1 Exception in F: G 2 Exception in Main: G

這是一個(gè)編譯時(shí)錯(cuò)誤break,continue或者goto語(yǔ)句將控制轉(zhuǎn)移出的finally塊。當(dāng)a?break,continue或goto語(yǔ)句出現(xiàn)在finally塊中時(shí),語(yǔ)句的目標(biāo)必須位于同一個(gè)finally塊中,否則會(huì)發(fā)生編譯時(shí)錯(cuò)誤。

return在finally塊中發(fā)生語(yǔ)句是編譯時(shí)錯(cuò)誤。

一個(gè)try語(yǔ)句的執(zhí)行過(guò)程如下:

  • 控制轉(zhuǎn)移到try塊。
  • 當(dāng)控件到達(dá)try塊的結(jié)束點(diǎn)時(shí):

    • 如果try語(yǔ)句有finally塊,finally則執(zhí)行該塊。
    • 控制權(quán)轉(zhuǎn)移到try聲明的終點(diǎn)。
  • 如果try在執(zhí)行try塊期間將異常傳播到語(yǔ)句:

    • 這些catch子句(如果有的話)按照外觀的順序進(jìn)行檢查,以便為異常找到合適的處理程序。如果catch子句未指定類(lèi)型,或指定異常類(lèi)型或異常類(lèi)型的基類(lèi)型:
      • 如果catch子句聲明了異常變量,則將異常對(duì)象分配給異常變量。
      • 如果catch子句聲明了異常過(guò)濾器,則會(huì)評(píng)估過(guò)濾器。如果計(jì)算結(jié)果為false,則catch子句不匹配,并且搜索將繼續(xù)通過(guò)catch適當(dāng)處理程序的任何后續(xù)子句。
      • 否則,該catch子句被視為匹配,并且控制被轉(zhuǎn)移到匹配catch塊。
      • 當(dāng)控件到達(dá)catch塊的結(jié)束點(diǎn)時(shí):
        • 如果try語(yǔ)句有finally塊,finally則執(zhí)行該塊。
        • 控制權(quán)轉(zhuǎn)移到try聲明的終點(diǎn)。
      • 如果try在執(zhí)行catch塊期間將異常傳播到語(yǔ)句:
        • 如果try語(yǔ)句有finally塊,finally則執(zhí)行該塊。
        • 該異常將傳播到下一個(gè)封閉try語(yǔ)句。
    • 如果try語(yǔ)句沒(méi)有catch子句或沒(méi)有catch子句匹配異常:
      • 如果try語(yǔ)句有finally塊,finally則執(zhí)行該塊。
      • 該異常將傳播到下一個(gè)封閉try語(yǔ)句。

一的語(yǔ)句finally在控制離開(kāi)塊總是被執(zhí)行try的語(yǔ)句。這是真實(shí)的,控制傳送是否發(fā)生正常的執(zhí)行結(jié)果,作為執(zhí)行的結(jié)果break,continue,goto,或return語(yǔ)句,或作為關(guān)于傳播異常出的結(jié)果try說(shuō)明。

如果在執(zhí)行finally塊期間拋出異常,并且未在同一finally塊中捕獲,則異常將傳播到下一個(gè)封閉try語(yǔ)句。如果另一個(gè)異常處于傳播過(guò)程中,則該異常將丟失。傳播異常的過(guò)程將在throw語(yǔ)句描述(throw語(yǔ)句)中進(jìn)一步討論。

在try一個(gè)塊try語(yǔ)句是可到達(dá)如果try語(yǔ)句是可到達(dá)。

一個(gè)catch一個(gè)的塊try語(yǔ)句是可到達(dá)如果try語(yǔ)句是可到達(dá)。

在finally一個(gè)塊try語(yǔ)句是可到達(dá)如果try語(yǔ)句是可到達(dá)。

try如果滿足以下兩個(gè)條件,則可以訪問(wèn)語(yǔ)句的結(jié)束點(diǎn):

  • 所述的結(jié)束點(diǎn)try塊是可到達(dá)的或者至少一個(gè)的結(jié)束點(diǎn)catch塊是可到達(dá)的。
  • 如果finally存在finally塊,則可以訪問(wèn)塊的結(jié)束點(diǎn)。

checked和unchecked語(yǔ)句

checked和unchecked語(yǔ)句用于控制溢出檢查上下文對(duì)整型算術(shù)運(yùn)算和轉(zhuǎn)換。

1 checked_statement 2 : 'checked' block 3 ; 4 5 unchecked_statement 6 : 'unchecked' block 7 ;

checked語(yǔ)句使得塊中的所有表達(dá)式都在已檢查的上下文中進(jìn)行計(jì)算,并且該unchecked語(yǔ)句會(huì)導(dǎo)致在未檢查的上下文中計(jì)算塊中的所有表達(dá)式。

該checked和unchecked語(yǔ)句完全等效于checked與unchecked運(yùn)營(yíng)商(checked和unchecked經(jīng)營(yíng)者,除了他們?cè)趬K而不是表達(dá)操作)。

lock語(yǔ)句

該lock語(yǔ)句獲取給定對(duì)象的互斥鎖,執(zhí)行語(yǔ)句,然后釋放鎖。

1 lock_statement 2 : 'lock' '(' expression ')' embedded_statement 3 ;

lock語(yǔ)句的表達(dá)式必須表示已知為reference_type的類(lèi)型的值。沒(méi)有為語(yǔ)句的表達(dá)式執(zhí)行隱式裝箱轉(zhuǎn)換(Boxing conversions),因此表達(dá)式的lock編譯時(shí)錯(cuò)誤表示value_type的值。

一個(gè)lock形式的聲明

lock (x) ...

其中x是reference_type的表達(dá)式,恰好相當(dāng)于

1 bool __lockWasTaken = false; 2 try { 3 System.Threading.Monitor.Enter(x, ref __lockWasTaken); 4 ... 5 } 6 finally { 7 if (__lockWasTaken) System.Threading.Monitor.Exit(x); 8 }

除了x僅評(píng)估一次。

在保持互斥鎖定的同時(shí),在同一執(zhí)行線程中執(zhí)行的代碼也可以獲取并釋放鎖定。但是,在鎖定釋放之前,阻止在其他線程中執(zhí)行的代碼獲取鎖定。

System.Type建議不要鎖定對(duì)象以同步對(duì)靜態(tài)數(shù)據(jù)的訪問(wèn)。其他代碼可能會(huì)鎖定相同的類(lèi)型,這可能導(dǎo)致死鎖。更好的方法是通過(guò)鎖定私有靜態(tài)對(duì)象來(lái)同步對(duì)靜態(tài)數(shù)據(jù)的訪問(wèn)。例如:

1 class Cache 2 { 3 private static readonly object synchronizationObject = new object(); 4 5 public static void Add(object x) { 6 lock (Cache.synchronizationObject) { 7 ... 8 } 9 } 10 11 public static void Remove(object x) { 12 lock (Cache.synchronizationObject) { 13 ... 14 } 15 } 16 }

using語(yǔ)句

該using語(yǔ)句獲取一個(gè)或多個(gè)資源,執(zhí)行語(yǔ)句,然后處置該資源。

1 using_statement 2 : 'using' '(' resource_acquisition ')' embedded_statement 3 ; 4 5 resource_acquisition 6 : local_variable_declaration 7 | expression 8 ;

資源是一個(gè)類(lèi)或?qū)崿F(xiàn)結(jié)構(gòu)System.IDisposable,它包括一個(gè)名為單個(gè)參數(shù)方法Dispose。使用資源的代碼可以調(diào)用Dispose以指示不再需要該資源。如果Dispose未調(diào)用,則最終會(huì)因垃圾收集而自動(dòng)處理。

如果形式resource_acquisition是local_variable_declaration則類(lèi)型local_variable_declaration必須是dynamic或可以隱式轉(zhuǎn)換為類(lèi)型System.IDisposable。如果resource_acquisition的形式是表達(dá)式,那么此表達(dá)式必須可以隱式轉(zhuǎn)換為System.IDisposable。

在resource_acquisition中聲明的局部變量是只讀的,并且必須包含初始化程序。如果嵌入語(yǔ)句試圖修改這些局部變量(通過(guò)賦值或發(fā)生編譯時(shí)間錯(cuò)誤++和--操作員),把它們的地址,或者將它們傳遞作為ref或out參數(shù)。

一個(gè)using語(yǔ)句被翻譯成三個(gè)部分:獲取,使用和處置。資源的使用隱式包含在try包含finally子句的語(yǔ)句中。該finally子句處理資源。如果null獲取了資源,則不會(huì)進(jìn)行任何調(diào)用Dispose,也不會(huì)拋出任何異常。如果資源屬于類(lèi)型dynamic,則在獲取期間通過(guò)隱式動(dòng)態(tài)轉(zhuǎn)換(隱式動(dòng)態(tài)轉(zhuǎn)換)動(dòng)態(tài)轉(zhuǎn)換IDisposable,以確保在使用和處置之前轉(zhuǎn)換成功。

一個(gè)using形式的聲明

using (ResourceType resource = expression) statement

對(duì)應(yīng)于三種可能的擴(kuò)展之一。何時(shí)ResourceType是非可空值類(lèi)型,擴(kuò)展為

1 { 2 ResourceType resource = expression; 3 try { 4 statement; 5 } 6 finally { 7 ((IDisposable)resource).Dispose(); 8 } 9 }

否則,當(dāng)ResourceType是可以為空的值類(lèi)型或除了以外的引用類(lèi)型時(shí)dynamic,擴(kuò)展為

1 { 2 ResourceType resource = expression; 3 try { 4 statement; 5 } 6 finally { 7 if (resource != null) ((IDisposable)resource).Dispose(); 8 } 9 }

否則,當(dāng)ResourceType是dynamic,擴(kuò)展

1 { 2 ResourceType resource = expression; 3 IDisposable d = (IDisposable)resource; 4 try { 5 statement; 6 } 7 finally { 8 if (d != null) d.Dispose(); 9 } 10 }

在任一擴(kuò)展中,resource變量在嵌入語(yǔ)句中是只讀的,并且d變量在嵌入語(yǔ)句中是不可訪問(wèn)的,并且對(duì)嵌入語(yǔ)句是不可見(jiàn)的。

允許實(shí)現(xiàn)以不同方式實(shí)現(xiàn)給定的using語(yǔ)句,例如出于性能原因,只要行為與上述擴(kuò)展一致即可。

一個(gè)using形式的聲明

using (expression) statement

有三個(gè)可能的擴(kuò)展。在這種情況下ResourceType隱含的是編譯時(shí)類(lèi)型expression,如果有的話。否則接口IDisposable本身用作ResourceType。該resource變量在嵌入語(yǔ)句中不可訪問(wèn)且不可訪問(wèn)。

當(dāng)resource_acquisition采用local_variable_declaration的形式時(shí),可以獲取給定類(lèi)型的多個(gè)資源。一個(gè)using形式的聲明

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

恰好等同于一系列嵌套u(yù)sing語(yǔ)句:

1 using (ResourceType r1 = e1) 2 using (ResourceType r2 = e2) 3 ... 4 using (ResourceType rN = eN) 5 statement

下面的示例創(chuàng)建一個(gè)名為的文件,log.txt并將兩行文本寫(xiě)入該文件。然后,該示例打開(kāi)相同的文件進(jìn)行讀取,并將包含的文本行復(fù)制到控制臺(tái)。

1 using System; 2 using System.IO; 3 4 class Test 5 { 6 static void Main() { 7 using (TextWriter w = File.CreateText("log.txt")) { 8 w.WriteLine("This is line one"); 9 w.WriteLine("This is line two"); 10 } 11 12 using (TextReader r = File.OpenText("log.txt")) { 13 string s; 14 while ((s = r.ReadLine()) != null) { 15 Console.WriteLine(s); 16 } 17 18 } 19 } 20 }

由于TextWriter和TextReader類(lèi)實(shí)現(xiàn)了IDisposable接口,因此該示例可以使用using語(yǔ)句來(lái)確保在寫(xiě)入或讀取操作之后正確關(guān)閉基礎(chǔ)文件。

yield語(yǔ)句

yield語(yǔ)句在迭代器塊(Blocks)中使用,以產(chǎn)生迭代器的枚舉器對(duì)象(Enumerator對(duì)象)或可枚舉對(duì)象(Enumerable對(duì)象)的值,或表示迭代結(jié)束。

1 yield_statement 2 : 'yield' 'return' expression ';' 3 | 'yield' 'break' ';' 4 ;

yield不是保留字;?它有之前用過(guò)的,只有當(dāng)特殊意義return或break關(guān)鍵字。在其他情況下,yield可以用作標(biāo)識(shí)符。

yield語(yǔ)句的出現(xiàn)位置有幾個(gè)限制,如下所述。

  • yield語(yǔ)句(任一形式)出現(xiàn)在method_body,operator_body或accessor_body之外是編譯時(shí)錯(cuò)誤
  • yield語(yǔ)句(任一形式)出現(xiàn)在匿名函數(shù)中是編譯時(shí)錯(cuò)誤。
  • yield語(yǔ)句(任一形式)出現(xiàn)在語(yǔ)句的finally子句中是編譯時(shí)錯(cuò)誤try。
  • yield return語(yǔ)句出現(xiàn)在try包含任何catch子句的語(yǔ)句中的任何位置都是編譯時(shí)錯(cuò)誤。

以下示例顯示了yield語(yǔ)句的一些有效和無(wú)效用法。

1 delegate IEnumerable<int> D(); 2 3 IEnumerator<int> GetEnumerator() { 4 try { 5 yield return 1; // Ok 6 yield break; // Ok 7 } 8 finally { 9 yield return 2; // Error, yield in finally 10 yield break; // Error, yield in finally 11 } 12 13 try { 14 yield return 3; // Error, yield return in try...catch 15 yield break; // Ok 16 } 17 catch { 18 yield return 4; // Error, yield return in try...catch 19 yield break; // Ok 20 } 21 22 D d = delegate { 23 yield return 5; // Error, yield in an anonymous function 24 }; 25 } 26 27 int MyMethod() { 28 yield return 1; // Error, wrong return type for an iterator block 29 }

隱式轉(zhuǎn)換(隱式轉(zhuǎn)換)必須存在于yield return語(yǔ)句中表達(dá)式的類(lèi)型到迭代器的yield類(lèi)型(Yield類(lèi)型)。

一個(gè)yield return語(yǔ)句的執(zhí)行過(guò)程如下:

  • 計(jì)算語(yǔ)句中給出的表達(dá)式,隱式轉(zhuǎn)換為yield類(lèi)型,并將其賦值給Current枚舉器對(duì)象的屬性。
  • 迭代器塊的執(zhí)行被暫停。如果yield return語(yǔ)句在一個(gè)或多個(gè)try塊內(nèi),finally則此時(shí)不執(zhí)行關(guān)聯(lián)的塊。
  • MoveNext枚舉器對(duì)象的方法返回true其調(diào)用者,指示枚舉器對(duì)象成功前進(jìn)到下一個(gè)項(xiàng)目。

對(duì)枚舉器對(duì)象MoveNext方法的下一次調(diào)用將從上次暫停的位置繼續(xù)執(zhí)行迭代器塊。

一個(gè)yield break語(yǔ)句的執(zhí)行過(guò)程如下:

  • 如果yield break語(yǔ)句被一個(gè)或多個(gè)try具有關(guān)聯(lián)finally塊的塊包圍,則控制最初被轉(zhuǎn)移到finally最內(nèi)層try語(yǔ)句的塊。當(dāng)控制到達(dá)finally塊的結(jié)束點(diǎn)時(shí),控制轉(zhuǎn)移到finally下一個(gè)封閉try語(yǔ)句的塊。重復(fù)此過(guò)程,直到執(zhí)行finally了所有封閉try語(yǔ)句的塊。
  • 控制權(quán)返回給迭代器塊的調(diào)用者。這是枚舉器對(duì)象的MoveNext方法或Dispose方法。

因?yàn)閥ield break語(yǔ)句無(wú)條件地將控制權(quán)轉(zhuǎn)移到其他地方,所以yield break語(yǔ)句的終點(diǎn)永遠(yuǎn)不可達(dá)。

轉(zhuǎn)載于:https://www.cnblogs.com/strengthen/p/9742587.html

總結(jié)

以上是生活随笔為你收集整理的C#6.0语言规范(八) 语句的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。