[.net 物件導向程式設計基礎] (7) 基礎中的基礎——流程控制語句
本來沒有這一節的內容,後來考慮到既然是一個系列文章,那麼就儘可能寫的詳細一些,本節參考了網上朋友所寫的例子,為的是讓更多小夥伴學習,提高,加薪,如有版權問題,請郵件我,我第一時間處理。
語句:是程式中的小指令,本節主要以流程控制語句為主要內容。
流程控制語句中最常用的三個是 選擇語句(即條件語句)、迴圈語句和異常處理語句
流程控制語句分類:
類別 關鍵字
選擇語句 if、else、switch、case
迴圈語句 do、for、foreach、in、while
跳轉語句 break、continue、default、goto、return
異常處理語句 throw、try-catch、try-finally
檢查和未檢查語句 checked、unchecked
非保護和固定語句 unsafe、fixed
鎖定語句 lock
1.條件語句
1.1 if - else
if (expression){}else{},其中expression是一個布林型別,true則執行第一區塊,false則執行else部分,這個小夥伴們肯定是相當滴熟悉了
使用這個語句有幾個要說明的地方:
A.如果if或else區塊部分只有一行,可以省略{}區塊符,例如:
int a,b,c;
if(a==b)
c++;
else
c--;
B.對於多個條件判斷可以使用if (expression){}else if(expression){}else{}
C.可以使用if else 巢狀
D.儘量避免使用多重巢狀和連續使用if
E.多重巢狀和多次if的情況,推薦使用下面的switch case語句
1.2 switch - case
switch 語句是通過將控制傳遞給其內部的一個 case 語句來處理多個選擇的流程控制語句。
switch 語句的基本結構:
switch (<testVar>)
{
case <comparisonVal1>:
<如果<testVar>等於<comparisonVal1>時執行的語句>
break;
case <comparisonVal2>:
<如果<testVar>等於<comparisonVal2>時執行的語句>
break;
……
case <comparisonValN>:
<如果<testVar>等於<comparisonValN>時執行的語句>
break;
default:
<如果沒有與<testVar>匹配的<comparisonValX>時執行的語句>
break;
}
(1) <testVar> 中的值與 case 語句中指定的每個 <comparisonValX> 值進行比較,如果有一個匹配,就執行為該匹配提供的語句。如果沒有匹配,就執行 default 部分中的程式碼。執行完每個部分中的程式碼後,還須有一個 break 語句。在執行完一個 case 塊後,再執行第二個 case 語句是非法的。
(2) break 語句將中斷 switch 語句的執行,而執行該結構後面的語句。
(3)還有另一種方法可以防止程式流程從一個 case 語句轉到下一個 case 語句。可以使用 return 語句。也可以使用 goto 語句,因為 case 語句實際上是在 C# 程式碼中定義標籤。
(4) 一個 case 語句處理完後,不能自由進入下一個 case 語句,但有一個例外。如果把多個 case 語句放(堆疊)在一起,其後加一行程式碼,實際上是一次檢查多個條件。如果滿足這些條件中的任何一個,就會執行程式碼,例如:
1 using System; 2 class SwitchTest 3 { 4 static void Main() 5 { 6 int n = 2; 7 switch(n) 8 { 9 case 1: 10 case 2: 11 case 3: 12 Console.WriteLine("It's 1, 2, or 3."); 13 break; 14 default: 15 Console.WriteLine("Not sure what it is."); 16 break; 17 } 18 } 19 }
輸出:
It's 1, 2, or 3.
每個 <comparisonValX> 都必須是一個常量。一種方法是提供字面值,另一種方式是使用常量。在這裡使用常量可讀性更好。
2.迴圈語句
使用迴圈語句可以讓程式多次執行相同的程式碼或程式碼塊,這些程式碼或程式碼塊稱為迴圈體。對於任何一個迴圈體來說,都應該提供一個跳出迴圈的條件,不同的迴圈語句提供不同的條件。
C# 語言中提供了以下4種迴圈語句:
· for
· foreach-in
· do-while
· while
2.1 for
for語句通常用來讓一條語句或一個語句塊執行一定的次數。
for語句的一般形式:
for ([initializers]; [expression]; [iterators])
{
statement
}
其中:
initializers 表示初始化迴圈計數器,如果有多個變數需要初始化,可用逗號隔開。
expression 是bool型別的表示式,用來測試迴圈是否終止。
iterators 表示增大或減少迴圈計數器的值。
statement 是需要迴圈執行的語句。
其執行流程為:
· 首先初始化 initializers。
· 接著,檢查 expression。如果為 true,執行 statement,並重新計算迴圈計數器的值。如果為 false,則退出迴圈。
· 返回上一步,繼續執行。
因為對 expression 的測試是在迴圈體執行之前,所以 for 語句可執行 0 次或多次。
for 語句的所有表示式都是可選的;例如,下列語句用於寫一個無限迴圈:
for (;;)
{
...
}
示例:
1 // for loop 2 using System; 3 class ForLoopTest 4 { 5 static void Main() 6 { 7 for (int i = 1; i <= 5; i++) 8 { 9 Console.WriteLine(i); 10 } 11 } 12 }
輸出:
1
2
3
4
5
2.2 for - in
foreach 語句為陣列或物件集合中的每個元素執行一遍迴圈體。通常用來遍歷某個集合,以獲取所需資訊,但不應用於更改集合內容以避免產生不可預知的副作用。
語法:
foreach (type identifier in expression)
{
staterment
}
其中:
type 表示 identifier 的型別。
identifier 表示集合元素的迴圈變數。
expression 表示物件集合或陣列表示式。集合元素的型別必須可以轉換成 identifier 的型別。
staterment 表示需要迴圈執行的語句。
對於陣列或集合中的每個元素,迴圈體都將執行一次。遍歷完所有的元素後,程式將退出 foreach 塊,執行後面的語句。
(1) foreach在陣列中的使用
該語句提供一種簡單、明瞭的方法來迴圈訪問陣列的元素。
例如,下面的程式碼建立一個名為 numbers 的陣列,並用 foreach 語句迴圈訪問該陣列:
1 int[] numbers = { 4, 5, 6, 1, 2, 3, -2, -1, 0 }; 2 foreach (int i in numbers) 3 { 4 System.Console.WriteLine(i); 5 }
對於多維陣列,使用巢狀的for迴圈可以更好地控制陣列元素。
(2) foreach 在集合中的使用
當對集合使用 foreach 語句時,該集合必須滿足一定的條件。
例如下面的 foreach 語句:
foreach (ItemType item in myCollection)
myCollection 必須滿足下面的要求。
集合型別:
必須是 interface、class 或 struct。
必須包括一個名叫 GetEnumerator 的例項方法,該方法返回一個型別,比如 Enumerator。
型別 Enumerator(類或結構)必須包含:
一個名為 Current 的屬性。型別為 ItemType 或可以轉換成 ItemType 的型別。它的屬性訪問器返回集合中的當前元素。
一個名叫 MoveNext 的方法。該方法用於增加計數器的值,如果集合中的元素個數小於計數器的值,該方法返回 true,否則返回 false。
2.3 do - while
do 語句重複執行括在 {} 裡的一個語句或語句塊,直到指定的表示式為 false 時為止。
do 迴圈的結構如下:
do
{
statement
} while (expression);
其中:
expression 為 bool 型別的表示式,或者是可以隱式轉換成 bool 型別的表示式,也可以是過載 true 和 false 操作符的型別的表示式。用來測試迴圈是否終止。
statement 是需要迴圈執行的語句。
do-while 結構先執行循體語句,然後判斷 while 條件是否為 true。如果為 true,將迴圈執行;如果為 false,則退出迴圈。因此 do-while 迴圈結構中的語句至少要執行一次。
while 語句後面的分號是必須的。
示例:下面示例中,只要變數 y 小於 5,do 迴圈語句就開始執行。
1 using System; 2 public class TestDoWhile 3 { 4 public static void Main () 5 { 6 int x = 0; 7 do 8 { 9 Console.WriteLine(x); 10 x++; 11 } 12 while (x < 5); 13 } 14 }
輸出:
0
1
2
3
4
2.4 While
當 while 語句中的判斷條件為 true 時,迴圈體將一直迴圈執行。
語法:
while (expression)
{
statement
}
其中:
expression 表示 bool 型別的表示式。用來測試迴圈是否終止。
statement 表示需要迴圈執行的語句。
while 語句和 do-while 語句不同,do-while 是先執行迴圈體再判斷條件,而 while 是先判斷條件。如果條件為 true,則執行迴圈體,否則將跳過迴圈體,執行 while 塊後面的程式碼。因此,while 語句中的迴圈體可能執行 0 次或多次。
在 while 迴圈體中,可以使用 break、goto、reture 或 throw 語句跳出迴圈。如果要跳轉到下一次迴圈,可在迴圈體中使用 continue 語句。
示例:
1 using System; 2 class WhileTest 3 { 4 static void Main() 5 { 6 int n = 1; 7 while (n < 6) 8 { 9 Console.WriteLine("Current value of n is {0}", n); 10 n++; 11 } 12 } 13 }
輸出:
Current value of n is 1
Current value of n is 2
Current value of n is 3
Current value of n is 4
Current value of n is 5
3. 跳轉語句
跳轉語句用於從程式的一個地方把執行控制轉移到另一個地方,每一條跳轉語句的應用都會增加程式執行流程的分支。
C#語言中可使用以下4種跳轉語句:
· break
· continue
· goto
· return
3.1 break 語句
break 語句用於中止當前執行的迴圈或它所在的 switch 語句,把控制交給迴圈或 switch 結構後面的語句。
示例:
在此例中,條件語句包含一個應該從 1 計數到 100 的計數器;但 break 語句在計數達到 4 後終止迴圈。
1 using System; 2 class BreakTest 3 { 4 static void Main() 5 { 6 for (int i = 1; i <= 100; i++) 7 { 8 if (i == 5) 9 { 10 break; 11 } 12 Console.WriteLine(i); 13 } 14 } 15 }
輸出:
1
2
3
4
下面的示例演示break在switch語句中的用法。
1 // break and switch 2 using System; 3 class Switch 4 { 5 static void Main() 6 { 7 Console.Write("Enter your selection (1, 2, or 3): "); 8 string s = Console.ReadLine(); 9 int n = Int32.Parse(s); 10 switch (n) 11 { 12 case 1: 13 Console.WriteLine("Current value is {0}", 1); 14 break; 15 case 2: 16 Console.WriteLine("Current value is {0}", 2); 17 break; 18 case 3: 19 Console.WriteLine("Current value is {0}", 3); 20 break; 21 default: 22 Console.WriteLine("Sorry, invalid selection."); 23 break; 24 } 25 } 26 }
輸入 1,則示例輸出為:
Enter your selection (1, 2, or 3): 1
Current value is 1
如果輸入 4,則輸出為:
Enter your selection (1, 2, or 3): 4
Sorry, invalid selection.
3.2 continue 語句
在迴圈體中使用 continue 語句將結束當前的迴圈,而進入下一次的迴圈。
示例:在此示例中,計數器最初是從 1 到 10 進行計數,但通過將 continue 語句與表示式 (i < 9) 一起使用,跳過了 continue 與 for 迴圈體末尾之間的語句。
1 using System; 2 class ContinueTest 3 { 4 static void Main() 5 { 6 for (int i = 1; i <= 10; i++) 7 { 8 if (i < 9) 9 { 10 continue; 11 } 12 Console.WriteLine(i); 13 } 14 } 15 }
輸出:
9
10
3.3 goto 語句
goto 語句將程式控制直接交給標記的語句。有以下形式:
goto identifier;
goto case constant-expression;
goto default;
其中:
identifier 表示一個標籤。
constant-expression 表示一個 switch-case 標籤。
在第一種形式中,identifier 指定位於當前迴圈體中的標籤,是一個與 goto 語句位於同一個迴圈體中的標籤。
goto 語句的常用方法是在 switch 語句中,將控制轉換傳遞到特定的 switch-case 標籤或 default 標籤。
有時也在多層巢狀的迴圈體中使用 goto 語句跳出多層迴圈。
如果在程式碼中宣告瞭標籤,但從未引用過它,編譯時將出現警告資訊。
示例:下面的示例演示了 goto 在 switch 語句中的使用。
1 using System; 2 class SwitchTest{ 3 static void Main() 4 { 5 Console.WriteLine("Coffee sizes: 1=Small 2=Medium 3=Large"); 6 Console.Write("Please enter your selection: "); 7 string s = Console.ReadLine(); 8 int n = int.Parse(s); 9 int cost = 0; 10 switch (n) 11 { 12 case 1: 13 cost += 25; 14 break; 15 case 2: 16 cost += 25; 17 goto case 1; 18 case 3: 19 cost += 50; 20 goto case 1; 21 default: 22 Console.WriteLine("Invalid selection."); 23 break; 24 } 25 if (cost != 0) 26 { 27 Console.WriteLine("Please insert {0} cents.", cost); 28 } 29 Console.WriteLine("Thank you for your business."); 30 } 31 }
如果輸入了 2,示例輸出:
Coffee sizes: 1=Small 2=Medium 3=Large
Please enter your selection: 2
Please insert 50 cents.
Thank you for your business.
下面的示例演示了使用 goto 跳出巢狀迴圈。
1 // Nested search loops 2 3 using System; 4 public class GotoTest1{ 5 static void Main() 6 { 7 int x = 200, y = 4; 8 int count = 0; 9 string[,] array = new string[x, y]; 10 // Initialize the array: 11 for (int i = 0; i < x; i++) 12 for (int j = 0; j < y; j++) 13 array[i, j] = (++count).ToString(); 14 // Read input: 15 Console.Write("Enter the number to search for: "); 16 // Input a string: 17 string myNumber = Console.ReadLine(); 18 // Search: 19 for (int i = 0; i < x; i++) 20 { 21 for (int j = 0; j < y; j++) 22 { 23 if (array[i, j].Equals(myNumber)) 24 { 25 goto Found; 26 } 27 } 28 } 29 Console.WriteLine("The number {0} was not found.", myNumber); 30 goto Finish; 31 Found: 32 Console.WriteLine("The number {0} is found.", myNumber); 33 Finish: 34 Console.WriteLine("End of search."); 35 } 36 }
如果輸入 44,則示例輸出:
Enter the number to search for: 44
The number 44 is found.
End of search.
3.4 return 語句
return 語句終止所在方法的執行,並將程式的控制返回給呼叫它的方法。它還可以返回一個可選值。如果方法為 void 型別,可以省略 return 語句。
return語句的形式如下:
return [expression];
其中:
expression 表示方法的返回值。當方法型別為 void 時不能使用 expression 引數。
示例:
在下面的示例中,方法 A() 以 double 值的形式返回變數 Area。
1 using System; 2 class ReturnTest 3 { 4 static double CalculateArea(int r) 5 { 6 double area = r * r * Math.PI; 7 return area; 8 } 9 10 static void Main() 11 { 12 int radius = 5; 13 Console.WriteLine("The area is {0:0.00}",
CalculateArea(radius)); 14 } 15 }
輸出:
The area is 78.54
4. 檢查和未檢查語句
C# 語句可以在檢查和非檢查情況下執行。在檢查情況下,算術溢位將引發異常;在非檢查情況下,算術溢位將被忽略,結果將被截斷。
· checked 指定檢查。
· unchecked 指定非檢查。
如果既未指定 checked 也未指定 unchecked,預設取決於外部因素,比如編譯器選項。
下列操作受溢位檢查的影響:
· 表示式對整型使用下列預定義操作符:
++ — -(一元) + - * /
· 整型間的顯式數字轉換。
/checked 編譯器選項使您可以為 checked 或 unchecked 關鍵字範圍內的所有非顯式整型算術語句指定檢查或非檢查情況。
4.1 checked 語句
checked 關鍵字用於對整型算術運算和轉換顯式啟用溢位檢查。
預設情況下,如果表示式產生的值超出了目標型別的範圍,則常數表示式將導致編譯時錯誤,而非常數表示式在執行時計算並將引發異常。不過,如果通過編譯器選項或環境配置在全域性範圍內取消了溢位檢查,則可以使用 checked 關鍵字來啟用此項功能。
示例:此示例演示如何對非常數表示式使用 checked。在執行時會報告溢位。
1 using System; 2 class OverFlowTest 3 { 4 static short x = 32767; // short型別的最大值 5 static short y = 32767; 6 // 對錶達式使用 checked 7 static int CheckedMethod() 8 { 9 int z = 0; 10 try 11 { 12 z = checked((short)(x + y)); 13 } 14 catch (System.OverflowException e) 15 { 16 Console.WriteLine(e.ToString()); 17 } 18 return z; 19 } 20 static void Main() 21 { 22 Console.WriteLine("Checked output value is: {0}", 23 CheckedMethod()); 24 } 25 }
示例輸出:
System.OverflowException: Arithmetic operation resulted in an overflow.
at OverFlowTest.CheckedMethod()
Checked output value is: 0
4.2 unchecked 語句
unchecked 關鍵字用於取消整型算術運算和轉換的溢位檢查。
在非檢查情況下,如果表示式產生目標型別範圍之外的值,則結果被截斷。例如:
1 unchecked 2 { 3 int val = 2147483647 * 2; 4 }
因為上面的計算在 unchecked 塊中執行,所以結果對於整數來說太大這一事實被忽略,並且 val 被賦予值 -2。預設情況下,啟用溢位檢測,這與使用 checked 具有相同的效果。
在上面的示例中,如果省略 unchecked,將產生編譯錯誤,因為表示式使用常數,結果在編譯時是已知的。unchecked 關鍵字還取消對非常數表示式的溢位檢測,這是為了避免在執行時導致 OverflowException。
unchecked 關鍵字還可以用作運算子,如下所示:
1 public int UncheckedAdd(int a, int b) 2 { 3 return unchecked(a + b); 4 }
示例:此示例通過在常數表示式中使用 unchecked,顯示如何使用 unchecked 語句。
1 using System; 2 class TestClass 3 { 4 const int x = 2147483647; // Max int 5 const int y = 2; 6 static void Main() 7 { 8 int z; 9 unchecked 10 { 11 z = x * y; 12 } 13 Console.WriteLine("Unchecked output value: {0}", z); 14 } 15 }
輸出:
Unchecked output value: -2
5. 非保護和固定
C# 中的語句可以在保護和非保護環境中執行,預設狀態為保護環境。使用帶指標的程式碼要求執行在非保護環境中。
關鍵字 unsafe:指定非保護環境。
使用了指向變數的指標,該變數就不能在記憶體中移動位置。這時,可使用fixed語句“固定”住這個變數。
關鍵字 fixed:防止變數重新定位。
5.1 unsafe語句
unsafe 表示非保護環境,該上下文是任何涉及指標的操作所必需的。
unsafe 可以用作方法、屬性、建構函式(不是靜態建構函式)的限定符。
例如:
unsafe static void FastCopy(byte[] src, byte[] dst, int count)
{
// 非保護環境:可以使用指標。
}
非保護環境的範圍包括從引數列表到方法的結尾,因此指標在以下引數列表中也可以使用:
unsafe static void FastCopy ( byte* ps, byte* pd, int count ) {...}
還可以使用不安全塊從而能夠使用該塊內的不安全程式碼。例如:
unsafe
{
// 非保護環境:可以使用指標。
}
若要編譯不安全程式碼,必須指定 /unsafe 編譯器選項。無法通過公共語言執行庫驗證不安全程式碼。
示例:
// 使用 /unsafe 編譯
1 using System; 2 class UnsafeTest 3 { 4 // 非保護方法:使用 int 型別的指標。 5 unsafe static void SquarePtrParam(int* p) 6 { 7 *p *= *p; 8 } 9 unsafe static void Main() 10 { 11 int i = 5; 12 // 非保護方法:使用地址操作符(&): 13 SquarePtrParam(&i); 14 Console.WriteLine(i); 15 } 16 17 }
輸出:
25
5.2 fixed 語句
fixed 關鍵字防止變數被重新定位。
fixed 語句的使用格式:
fixed ( type* ptr = expr ) statement
其中:
type 表示未管轄的型別或 void。
ptr 表示指標名稱。
expr 表示隱式轉換成 type* 的表示式。
statement 表示可執行的語句或語句塊。
fixed 語句只能用在 unsafe 環境中執行。
fixed 語句用來設定指向變數的指標,並在 statement 執行過程中固定變數的位置。如果不使用 fixed,指向已處理變數的指標就可能重新移動位置,該指標也就失去了作用。實際上,如果不使用 fixed 語句,C# 編譯器是不允許設定指向已處理變數的指標的。
在非保護模式中,可以在堆疊上分配記憶體,這裡的記憶體不受垃圾回收器的管理,因此可以不需要固定。
示例:
class Point { public int x, y; } class FixedTest { // Unsafe method: takes a pointer to an int. unsafe static void SquarePtrParam(int* p) { *p *= *p; } unsafe static void Main() { Point pt = new Point(); pt.x = 5; pt.y = 6; // Pin pt in place: fixed (int* p = &pt.x) { SquarePtrParam(p); } // pt now unpinned Console.WriteLine("{0} {1}", pt.x, pt.y); } }
輸出:
25 6
6. 鎖定語句
lock 關鍵字將語句塊標記為臨界區,方法是獲取給定物件的互斥鎖,執行語句,然後釋放該鎖。此語句的形式如下:
1 Object thisLock = new Object(); 2 lock (thisLock) 3 { 4 // 臨界區程式碼 5 }
lock 確保當一個執行緒位於程式碼的臨界區時,另一個執行緒不進入臨界區。如果其他執行緒試圖進入鎖定的程式碼,則它將一直等待(即被阻止),直到該物件被釋放。
通常,應避免鎖定 public 型別,否則例項將超出程式碼的控制範圍。常見的結構 lock (this)、lock (typeof (MyType)) 和 lock ("myLock") 違反此準則:
· 如果例項可以被公共訪問,將出現 lock (this) 問題。
· 如果 MyType 可以被公共訪問,將出現 lock (typeof (MyType)) 問題。
· 由於程式中使用同一字串的任何其他程式碼將共享同一個鎖,所以出現 lock(“myLock”) 問題。
最佳做法是定義 private 物件來鎖定, 或 private shared 物件變數來保護所有例項所共有的資料。
示例:下例顯示的是在 C# 中使用執行緒的簡單示例。
1 using System; 2 using System.Threading; 3 class ThreadTest{ 4 public void RunMe() 5 { 6 Console.WriteLine("RunMe called"); 7 } 8 static void Main() 9 { 10 ThreadTest b = new ThreadTest(); 11 Thread t = new Thread(b.RunMe); 12 t.Start(); 13 } 14 }
輸出:
RunMe called
7. 異常處理語句
try - catch - finally
try裡面是執行程式碼,其中的程式碼"可能"產生異常.
catch是對產生異常後的處理程式碼,可以丟擲異常,也可以顯示異常,也可以彈出某中提示,總之catch裡是任何程式碼都行,如果你知道這鐘異常產生的原因,可以列印此原因,也可以對此原因進行相應的處理,同時可以為多個catch,每個catch(異常型別) 用多個catch來捕獲多種異常,也可以用所有異常的父類來捕獲(這樣就不用寫多個catchl了).
假如try中產生了異常,那麼try從產生異常開始到try結束的這段程式碼將不會執行,轉而去執行catch.
finally是try執行完後執行(沒發生異常)或者在catch後執行(發生了異常),也就是說finally無論怎麼樣,都會執行.
==============================================================================================
返回目錄
<如果對你有幫助,記得點一下推薦哦,有不明白的地方或寫的不對的地方,請多交流>
==============================================================================================