流程控制

C#中提供了以下控制關鍵字:

選擇控制:if,else,switch,case

循環控制:while,do,for,foreach

跳轉語句:break,continue

編譯控制:#if,#elif,#else,#endif

異常處理:try,catch,finally

1,if語句

if(boolean-expression) embedded-statement

or

if(boolean-expression) embedded-statement

 else embedded-statement

如果if或else之後的語句只包含一條執行語句,則嵌套的部分的大括號可以省略.如果包含

了兩條以上的執行語句,則一定要加上大括號.

C#中if語句中的條件只允許是bool型.

2,switch語句

if語句每次判斷只能實現兩條分支,如果要實現多种選擇的功能,那麼可以采用switch語

句.switch語句根據一個控制表達式的值選擇一個內嵌語句分支來執行.它的一般格式為:

switch(controlling-expression)

{

  case constant-expression

    embedded-statements

  case constant-expression

    embedded-statements

  default;

    embedded-statements

}

代碼示例:

int x=int(x/10)

switch(x)

{

  case 10:y=4;break;

  case 9 :y=4;break;

  case 8 :y=3;break;

  case 7 :y=2;break;

  case 6 :y=1;break;

  default:y=0;

}

在C#中,不準遍歷.在case標簽後不出現break語句,在C#中不允許這樣.如果標簽項沒有出現

break語句或是跳轉語句goto,編譯器將會要求程序員加上.

如果想像,C,C++那樣,執行完後繼續遍歷其它的語句,那也不難,只需要明確地加入這兩條跳

轉語句即可:

goto case label:跳至標簽語句執行

goto default:跳至default標簽執行

下面的寫法是正確的.

total=365;

switch(month)

{

  case 1:total-=31;goto case 2;

  case 2:total-=28;goto case 3;

  case 3:total-=30;goto case 4;

  case 4:total-=31;goto case 5;

  case 5:total-=30;goto case 6;

  case 6:total-=31;goto case 7;

  case 7:total-=30;goto case 8;

  case 8:total-=31;goto case 9;

  case 9:total-=30;goto case 10;

  case 10:total-=31;goto case 11;

  case 11:total-=30;goto case 12;

  case 12:total-=31;goto case default;

  default:total+=day;

}

在避免了C,C++中常出現的由於漏寫break而造成的錯誤的同時,"不準遍歷"的原則還使得我

們可以任意排列switch語句中的case項而不會影響switch語句的功能.

另外,一般來說每個switch項都以break,goto case或goto default結束,但實際上任何一种

不導至"遍歷"的結構都是允許的,例如throw和return語句同樣可以跳出控制之外,因而下便

是正確的:

switch(i)

{

  case 0:

    while(true) F();

  case 1:

    throw new ArgumentException();

  case 2:

    return;

}

C#的switch語句與c,c++的另一個不同點是,c#可以把字符串當成常量表達式來使用.所以

switch語句的控制類型可以是string類型.

如下面的例子:

string text=GetButtonCaption();

switch(text)

{

  case "OK"     :ShowMessage("Save the change and exit");break;

  case "Retry"  :ShowMessage("return and retry");break;

  case "Abort"  :ShowMessage("Abort the change and exit");break;

  case "HELP"   :ShowMessage("Get help from system");break;

}

而且C#中case標簽的引用值允許是null.

循環語句

C#中提供了四种循環語句,分別適用於不同的情形:

while語句

do while語句

for語句

foreach語句

while語句

有條件地將內嵌語句執行0遍或多次,語句的格式為:

while(boolean-expression)

  embedded-statement

執行順序是:

計算布爾表達式boolean-expression的值

當布爾表達式的值為真時,執行內嵌語句embedded-statement一次,程序再回到計算布你表

達式.

當布爾表達式的值為假時,while循環結束.

看一個簡單的例子,該例在數組中查找一個指定的值,如找到就返回數組下標,否則返回報告

.

using system;

class test

{

  static int find(int value,int[] array)

  {

    int i=0;

    while (array[i]!=value)

    {

      if(++i>array.length)

        console.writeline("can not find");

    }

    return i;

  }

  static void Main()

  {

    console.writeline(find(3,new int[]{5,4,3,2,1}));

  }

}

while語句中允許使用break語句結束循環,執行後續語句;也可以用continue語句來停止內

嵌語句的執行,繼續進行while循環.

下面是一個計算整數x的階乘值:

long y=1;

while(true)

{

  y*=x;

  x--;

  if(x==)

    break;

}

do while語句

do while與while不同的是,它將內嵌語句執行一次(至少一次)或多次.它的格式如下:

do

  embedded-statement

while(boolean-expression)

執行順序如下:

首先執行內嵌語句embedded-statement一次;

計算布爾表達式boolean-expression的值,為true則回到第一步,為false則終止do循環.

在do while循環語句同樣允許用break語句和continue語句實現while語句中相同的功能.

下面是用do while來實現求整數的階乘

long y=1;

do

{

  y*=x;

  x--;

}

while(x>0)

for語句

在事先知道循環次數的情況下,使用for語句是比較方便的.for語句的格式為:

for(initalizer;condition;iterator)

  embedded-statement

其中initalizer;condition;iterator這三項都是可選項.initializer為循環控制變量做初

始化,循環控制變量可以有一個或多個(用逗號隔開);condition為循環控制條件,也可以有

一個或多個語句;iterator按規律改變循環控制變量的值.

如果忽略了條件,你就可以產生一個死循環,要用跳轉語句(break/goto)才能退出.

for(;;)

{

  break;

}

for語句執行順序如下:

按書寫順序將initializer部份(如果有的話)執行一遍,為循環控制變量賦初值;

測試condition(如果有的話)中的條件是否滿足;

若沒有condition項或條件滿足,則執行內嵌語句一遍,按iterator改變循環環控制變量的值

,回到第二步執行;

若條件不滿足,則for循環終止.

下面的例子是打印楊輝三角形:

using system;

{

  public static void Main()

  {

    int [,] a=new int[5,5];

    a[0,0]=1;

    for (int i=1;i<=5;i++)

    {

      a[i,0]=1;

      a[i,i]=1;

      for (int j=1;j<i;j++)

      {

        a[i,j]=a[i-1,j-1]+a[i-1,j];

      }

    }

    for(int 1=0;i<5;i++)

    {

      for(int j=0;j<i;j++)

      {

        Console.WriteLine("{0}",a[i][j]);

      }

      Consolw.WriteLine();

    }

  }

}

程序運行的結果為:

1

1  1

1  2  1

1  3  3  1

1  4  6  4  1

1  5  10 10 5  1

求整數的階乘為例,代碼我們可以這樣寫:

for(long y=1;x>0;x--)

  y*=x;

同樣也可以用break和continue語句,來和循環判斷符合語中的邏輯表達式來配合使用,到達

控制循環的目的.

如果要求打印除7以外的0到9的數字,只要在for循環執行到7時,跳過打印語句就可以了.

for(int i=0;i<0;i++)

{

  if(i==7) continue;

  Console.WriteLine(i);

}

Foreach語句

這表示收集一個集合中的各遠素,並針對各個元素執行內嵌語句,語句的格式為:

foreach(type identifier in expression)

  embedded-statement

其中(type)和標識符(identifier)用來聲明循環變量,表達式(expression)對應集合.每執

行一次內嵌語句,循環語句,循環變量就依次取集合中的一個元素代入其中.在這里,循環變

量是一個只讀局部變量,如果試圖改變它的值或將它作為一個ref或out類型的參數傳遞,都

將引發編譯時錯誤.

foreach語句中的expression必須是集合類型,如果該集合的元素類型與循環變量類型不一

致,則必須有一個顯示定議的從集合中的元素類型到循環變量元素類型的顯式轉換.

究竟什麼樣的類型算是集合類型呢?我們從語句上給出集合類型的定議:

該類型支持一個形為GetEnumerator()的公有的非靜態方法,該方法返回類型為結構,類或是

接口.

形為GetEumerator()的方法返回的結構,類或接口應當包含一個公有的非靜態的方法

MoveNext(),該方法的返回類型為布爾型.

形為GetEumerator()的方法返回的結構,類或接口應當包含一個公有的非靜態的屬性

Current,該屬性可以讀出.

如果一個類型同時滿足以上三個條件,該類型稱為集合類型.Current屬性的類型叫作該集合

類型的元素類型.

數組類型是支持foreach語句的,對於一維數組,執行順序是從下標為0的元素開始,一直到數

組的最後一個元素;對於多維數組,元素下標的遞增是從最右邊那一維開始的,依次類推.

同樣break和continue可以出現在foreach語句中,功能不變.

條件編譯

用於定議符號和取消符號定議的預處理指令:#define和#undef.

條件編譯指隻有以下四种:#if,#elif,#else,#endif.它們和c#中的if句語有類似的作用.你

可以在指隻中使用邏輯操作符與(&&),或(||)和取反操作符(!)等.它們在程序中的出現的先

後順序必須是這樣:

一條#if語句(必須有)

零或多條#elif語句

零或一條#else語句

一條#endif語句(必須有)

下面舉個例子說明它們的用法:

#define Debug

class Class1

{

#if Debug

  void Trace(string s){}

#end if

}

執行時,由於第一行已經使用#define指令定議了符號debug,#if的條件滿足,這段代碼等同

於:

class Class1

{

  void Trace(string s){}

}

再比如:

#define A

#define B

#undef C

class D

{

  #if c

    void f(){}

  #elif A && B

    void I(){}

  #else

    void G(){}

  #endif

}

不難看出,它實際編譯的效果等同於:

class D

{

  void I(){}

}

發出錯誤和警告信息

相應的指令是#warning和#error

下面的程序展示了它們的用法

#define DEBUG

#define RELEASE

#define DEMO VERSION

#if DEMO VERSION && !DEBUG

  #warning you are building a demo version

#endif

#if DEBUG && DEMO VERSION

  #error you cannot build a debug demo version

#endif

using system;

class Demo

{

  public static void Main()

  {

    Console.WriteLine("Demo application");

  }

}

在本例中,當你試圖創建一個演示版時,會出一個警告信息:

you are building a demo version.

當試圖創建調試演示版時,會觸發錯誤信息:

you cannot build a debug demo version.

異常處理語句

在C#中,所有的異常都表為一個類的實例,這個類繼承自System.Exception類.

checked和unchecked語句就是用來控制整型算術運算和轉換中的溢出檢測的.下面以一個計

算階乘的例子說明它們的用法.

using system;

class Factorial

{

  public static void Main(string [] args)

  {

    long nFactorial=1;

    long nComputerto=Int64.Parse(args[0]);

    long nCurDig=1;

    for(nCurDig=1;nCurDig<=nComputerto;nCurDig++)

    {

      checked{nFactorial*=nCurDig;}

    }

    Console.WriteLine("{0}! is {1}",nComputerto,nFactorial);

  }

}

當運算發生溢出時,程序將發出異常信息:

System.OverflowException at Factorial.main(System.String[])

引發異常的條件

異常可以以兩种不同的方式引發:

throw語句無條件,即時的拋出異常.

C#語句和表達式執行過程中激發了某個異常的條件,使得操作無法正常結束,從而引發異常.

throw語句拋出一個異常:

throw expression

帶有表達式的throw語句拋出的異常是在計算這個表達式時產生的.這個表達式必須表示一

個System.Exception類型或它的派生類型的值.

異常處理語句

異常處理由try語句來處理的.

以下是它的三种可能的形式:

try catch(s)

try finally

try catch(s) finally

當一個異常被拋出以後,程序將控制權轉移給try語句中第一個能夠處理該異常的catch子句

.這個從異常拋出到控制轉移給合適的異常處理語句的過程就叫做異常傳播.

異常傳播包括重復執行以下步驟,直到找到一個與該異常相匹配的catch子句.

由里層到外層的執行每一個包圍拋出點(異常被拋出的最初位置)的try語句:如果當前的try

塊包含一或多條catch子句,那麼將按照這些子句的出現順序對它們一一檢查以定位適合該

異常的處理.所謂適合該異常的處理也就是第一個定議了該異常類型或其基類型的catch子

句.一般catch子句可以匹配任何類型的異常.一旦找到與該異常匹配的catch子句,異常傳播

也就結束了,程序控制轉移到該catch子句執行.否則,如果當前的try塊含有finally塊的話,

就執行finally塊.如果該塊又拋出另一個異常,則當前的異常將被終止,如果沒有,則當

finally塊執行完以後,再繼續異常的處理.

如果當前的成員函數調用中沒能定位異常處理,則調用終止.並且在該成員函數調用點將該

異常拋給調用者,重復執行上一步.

如果該異常終止了當前線程或進程的所有成員函數調用,則說明該線程或進程中不存在對異

常的處理.它將自行終止.

下面的例子中我們演示了try catch語句的使用以及再次拋出異常.

using system;

class test

{

  static void f()

  {

    try

    {

      g();

    }

    catch(Exception e)

    {

      Console.WriteLine("Exception in f:" + e.message);

      e=new Exception("F");

      throw;

    }

  }

  static void g()

  {

    throw new Exception("G");

  }

  static void Main()

  {

    try

    {

      f();

    }

    catch (Exception e)

    {

      Console.WriteLine("Exception in Main" + e.Message);

    }

  }

}

F方法捕捉了一個異常,向控制臺寫了一些診斷信息,改變異常變量的內容,然後將該異常再

次拋出.這個被再次拋出的異常與最初捕捉到的異常是同一個.因此程序的輸出結果如下:

Exception in F:G

Exception in Main:G

當try語句執行完成後,finally塊中的語句必將被執行.不論是否會發生由以下原因導致的

程序控制轉移:

普通操作的結果;

執行break,continue,goto或return語句的結果;

將異常傳播到語句之外的結果.

我們用一個例子來證明finally子句的運行

using System;

class Jumptest

{

  public static void Main()

  {

    try

    {

      Console.WriteLine("try");

      goto leave;

    }

    finally

    {

      Console.WriteLine("finally");

    }

    leave:

          Console.WriteLine("leave");

  }

}

程序動行的結果為

try

finally

leave

由此可見,finally子句總能被執行.因此我們可以利用try finally來清除異常.

如果在執行finally塊時拋出了一個異常,這個異常將被傳播到下一輪try語句中去.如果在

異常傳播的過程中又發生了另一個異常,那麼這個異常將被丟失.

下面這個列子

float x,y,z;

try

{

  z=Math.Sqrt(x*x-y*y);

}

catch

{

  z=Math.Sqrt(y*y-x*x);

}

finally

{

  z=z+x;

}

其中第一個try語句捕捉負數開根號的異常,並與第二個catch語句配合達到取絕對值的目的.

 


申明

非源创博文中的内容均收集自网上,若有侵权之处,请及时联络,我会在第一时间内删除.再次说声抱歉!!!