[.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無論怎么樣,都會執行.
==============================================================================================
返回目錄
<如果對你有幫助,記得點一下推薦哦,有不明白的地方或寫的不對的地方,請多交流>
==============================================================================================