iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 25
1
Modern Web

C#與ASP.Net入門-我要成為工程師!!系列 第 25

Day25-C#-凡事都可能有例外~出其不意就是人森阿(´_ゝ`)(例外處理try-catch)

凡事都可能有例外,當然自己的程式碼也是XD
有時候是自己的思慮不周寫了爛code,有時候是外部環境改變,有時候就是天時地利 加上人品不好(XD?) code就是掛了XD
讓我們來想想,當程式發生異常狀況導致無法繼續執行,這時候錯誤訊息直接顯示...

  • 麻瓜使用者:陣列索引超出範圍?陣列是什麼?能吃嗎?阿我剛剛點的到底有沒有成功?天啊中毒了嗎?是不是要關機重開?(各種小劇場....)
  • 駭客:喔~原來是錯在這個地方啊~(憋不住的笑意)

身為一個積極上進(?)的programer,這時候就會想,如果我可以在發生意料之外的錯誤時先做一些處理,或許可以避免掉一些麻煩?甚至先補救,不就沒人知道發生什麼事了嗎/images/emoticon/emoticon07.gif

這時候, try{...}catch{...}finally{...} 敘述就派上用場了!

=================================================================

例外處理架構

try
{
    //主程式/需要監控的區塊
}
catch(例外類別一 ex)
{
    //例外類別一處理方法
}
catch(例外類別二 ex)
{
    //例外類別二處理方法
}
...
catch(例外類別N ex)
{
    //例外類別N處理方法
}
finally
{
    //不管怎樣都會執行的區塊
}

說明:

  1. catch:catch{}可以有很多個,會由上而下逐一檢查,符合例外類別即執行{}內敘述,下方的其他catch則不再處理。
  2. ex 自訂的例外變數名稱,若例外類別成立,ex物件會自動建立。
  3. Exception類別是.NET Framework中所有例外狀況的基礎類別。許多衍生的類別都繼承自Exception類別。
  4. finally區段不一定要有,清資源會放在這。

來看看一個你如果處理陣列應該有遇到過(吧)的例外,IndexOutOfRangeException

static void Main(string[] args)
{
    //上期發票中頭獎人名
    string[] luckyman = { "總算有好事的小明", "路上撿到彩卷的阿花","被老婆盜刷的阿宏"};
    Console.WriteLine(luckyman[3]);
    Console.ReadKey();
}

因為luckyman[3]不存在,當你執行這段程式碼,程式會直接不讓你跑,IDE還會跳出這個錯誤訊息
https://ithelp.ithome.com.tw/upload/images/20190926/20120055hycIW6x9td.png

於是我們改一下程式碼,順便看看ex是什麼

static void Main(string[] args)
{
    try
    {
        Console.WriteLine(luckyman[3]);
    }
    catch (IndexOutOfRangeException ex)
    {
        Console.WriteLine(ex.ToString());//把ex印出來
    }
    Console.ReadKey();
}

https://ithelp.ithome.com.tw/upload/images/20190926/20120055Cv9eDbM2MC.png

當然如果要讓使用者看的話絕對不是丟給他錯誤訊息,於是再改一下程式碼

static void Main(string[] args)
{
    try
    {
        Console.WriteLine(luckyman[3]);
    }
    catch (IndexOutOfRangeException ex)
    {
        Console.WriteLine("沒有第四個人了啦~");
    }
    finally
    {
        Console.WriteLine("不說了我要去對發票了");//不管有沒有遇到錯誤都會執行
    }
    Console.ReadKey();
}

https://ithelp.ithome.com.tw/upload/images/20190926/2012005549LtPWVnVe.png

就是這樣~這期發票9/25開獎囉~不說了我要去對發票了~

如果我明天沒有發文章...恩...你知道的/images/emoticon/emoticon29.gif

================================================================

例外處理類別

常碰到的例外處理類別有以下(寫到這一篇6個也遇到5個了....),完整可以參考MSDN:
另外感謝下方小朱大大補充

類別 說明
ArgumentOutOfRangeException 引數超出有效值的範圍
DivideByZeroException 整數或Decimal除法運算中的分母為零
IndexOutOfRangeException 索引超出陣列或集合的範圍
InvalidOperationException 方法呼叫在物件的目前狀態中無效
FormatException 引數格式無效或複合格式字串格式(如:Datetime)不正確
NullReferenceException 當嘗試對 Null 物件(未初始化)取值
InvalidCastException Convert方法的轉型錯誤,如值域不足、型態錯誤...等
Exception 執行時期所產生錯誤,可以捕捉所有例外

另外Exception(最後一格)這個錯誤類別範圍太粗略了要小心使用,若使用也應該放在最後一個catch,否則會有編譯錯誤。

================================================================

自訂例外-throw

遇到特殊錯誤,系統沒有提供此判斷時,也可以另外寫程式來處理。以下示範指定ArgumentOutOfRangeException來作為例外類別。

一年有12個月,但不會有例外判斷會幫你判定輸入值控制在1-12

static void Main(string[] args)
{
    int month = 0;
    try
    {
        Console.WriteLine("請輸入月份");
        month = Convert.ToInt32(Console.ReadLine());
        if (month > 12 || month<1)
        throw new ArgumentOutOfRangeException();//指定丟出這個例外類別,要new喔!
    }
    catch (ArgumentOutOfRangeException ex)
    {
        Console.WriteLine("沒有這個月份啦!我書讀得少不要騙我R");
    }
    Console.ReadKey();
}

https://ithelp.ithome.com.tw/upload/images/20190926/20120055uiBnOepyuH.png

當然也可以繼承Exception類別自創例外類別,但須用到繼承、覆寫等概念尚未學習我們這裡先不談,可以參考這篇文章

================================================================

怎麼下中斷點

發生錯誤要怎麼找到底錯在哪???

一直忘了介紹IDE這個好用的debug功能-設中斷點!

你可以在編輯程式碼區左列按一下加上紅點點

https://ithelp.ithome.com.tw/upload/images/20190926/20120055Fnj4OtC2QY.png

程式跑到這個點就會暫停一下,這時候你可以把游標移到想確認的地方做確認,例如到底有沒有讀到值等等

https://ithelp.ithome.com.tw/upload/images/20190926/201200559fOu0PwjeN.png

然後目光移到最上方工具列,可以選擇繼續執行或是逐步執行,可以更快找到程式碼到底哪裡有問題唷
https://ithelp.ithome.com.tw/upload/images/20190926/20120055Prvc7osM3F.png

=================================================================

參考資料

MSDN-try-catch
書籍:
Visual C# 2017程式設計經典
從零開始學Visual C# 2015程式設計


上一篇
Day24-C#-參數的傳遞方式-Call By Value/Call By Reference/Output parameter
下一篇
Day26-[ASP.NET]ASP.NET 網頁簡介、頁面介紹
系列文
C#與ASP.Net入門-我要成為工程師!!31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中
0
YoChen
iT邦研究生 1 級 ‧ 2019-09-27 09:41:16
if (month > 12 || month < 0) { } // month < 1就好囉~

這個地方有錯哦~

感謝!已修正XD

1
小朱
iT邦新手 4 級 ‧ 2019-09-27 09:54:46

其實最常見的是 NullReferenceException,尤其是初入門的人愈容易碰到。
原因是存取一個未初始化的物件變數。
還有一種 InvalidCastException,在叫用 Convert 的方法做數值轉型時的問題,例如值域不足、格式不對 (字串轉數字、浮點數、布林值時) 等。

感謝大大!學到了!XD

0
ayugioh2003
iT邦新手 2 級 ‧ 2021-04-18 18:27:29
    string[] luckyman = { "總算有好事的小明", "路上撿到彩卷的阿花","被老婆盜刷的阿宏"};

這邊的 luckyman 好像是陣列形式 (中括號),這邊變成是尖括號了 ~

我要留言

立即登入留言