重學c#系列

舉個例子:

static void Main(string[] args)

{

FileStream sw = null;

try

{

? sw = new FileStream(@"C:\test\test.txt", FileMode.Open, FileAccess.ReadWrite)

? sw.Write(new byte[1]);

}

catch (DirectoryNotFoundException ex)

{

//文件目錄沒有找到異常

Console.WriteLine(ex);

}

catch (FileNotFoundException ex)

{

//文件沒有找到異常

Console.WriteLine(ex);

}

catch (IOException ex)

{

//io操作異常

Console.WriteLine(ex);

}

finally

{

sw?.Flush();

sw?.Close();

}

}

沒有找到找到相應的catch,那么會一步一步往下找。

首先是查看DirectoryNotFoundException ,然后是FileNotFoundException,只要是io操作出現(xiàn)問題都會是IOException。

那么我該如何知道DirectoryNotFoundException、FileNotFoundException、IOException他們的關系呢?

這時候就需要看圖了,圖不大,可以記下來。

如圖:

上面這些是常用的,可以說是必會的吧,下面介紹一下他們的作用。

異常 詳細

ArgumentException 方法參數(shù)異常

ArgumentNullException 參數(shù)為空異常

ArgumentOutOfRangeException 索引小于零或超出數(shù)組邊界時,嘗試對數(shù)組編制索引時引發(fā)

ArithmeticException 算術運算期間出現(xiàn)的異常的基類,例如 DivideByZeroException 和 OverflowException。

OverflowException 當在檢查的上下文中執(zhí)行的算術、強制轉(zhuǎn)換或轉(zhuǎn)換運算導致溢出時引發(fā)的異常

StackOverflowException 執(zhí)行堆棧由于有過多掛起的方法調(diào)用而用盡時引發(fā);通常表示非常深的遞歸或無限遞歸。

IOException 發(fā)生I/O錯誤時引發(fā)的異常。

FileLoadException 找到托管程序集但不能加載時引發(fā)的異常

FileNotFoundException 文件沒有找到

EndOfSteamExcetion 讀操作試圖超出流的末尾時引發(fā)的異常。

DriveNotFoundException 當嘗試訪問的驅(qū)動器或共享不可用時引發(fā)的異常。

ApplicationException 用作應用程序定義的異常的基類

TargetInvocationException 由通過反射調(diào)用的方法引發(fā)的異常

CompositionException 表示在 CompositionContainer 對象中進行組合期間發(fā)生一個或多個錯誤時引發(fā)的異常。

ChangeRejectedException 一個指示部件在組合期間是否已遭拒絕的異常。

有些異常是我們寫代碼不應該去產(chǎn)生異常的,比如說ApplicationException作為基類的異常,如果出現(xiàn)這些異常一般是我們代碼寫的有問題,

而不是我們的主觀因素。應從 Exception 類(而不是 ApplicationException 類)派生自定義異常。 不應在代碼中引發(fā) ApplicationException 異常,除非你

打算重新引發(fā)原始異常,否則不應捕獲 ApplicationException 異常。 這里舉個例子:TargetInvocationException的基類是ApplicationException,這個是

由通過反射調(diào)用的方法引發(fā)的異常。如果產(chǎn)生這個問題,可以想象是我們反射使用的有問題。同樣如果我們?nèi)懛瓷涞某绦颍覀儾粦撊atch這個,而是讓他直接

報錯,表示代碼就不應該這么寫,出錯然后去解決。

好吧,回到原問題上,假如沒有找到兼容性的catch塊那么會怎么樣呢?

那么實驗一下吧。

實驗如下:

會拋出異常的,所以我們寫代碼的時候需要確保最后一個一定能捕獲到異常的,如果sw.Write(new byte[1]);出現(xiàn)錯誤那么非托管資源就沒有釋放。

那么如何萬一我們沒有捕獲到異常也能是否非托管資源呢?使用using。

static void Main(string[] args)

{

try

{

using (var sw = new FileStream(@"C:\test\test.txt", FileMode.Open, FileAccess.ReadWrite))

{

sw.Write(new byte[1]);

}

}

catch (DirectoryNotFoundException ex)

{

//文件目錄沒有找到異常

Console.WriteLine(ex);

}

finally

{

}

}

這樣寫無論是否異常,那么都會釋放非托管資源。這個是可以實驗的,我把我的實驗貼一下。

上面的說明已經(jīng)被關閉了,我們再次關閉的時候?qū)a(chǎn)生異常。這個using可以看下IL,就清楚其中的原理。

異常過濾器

異常過濾器是c#的東西,這里只是做簡單的介紹,后面異常代碼優(yōu)化章節(jié)中會重點介紹。

public static bool ConsoleLogException(Exception e)

{

var oldColor = Console.ForegroundColor;

Console.ForegroundColor = ConsoleColor.Red;

Console.WriteLine("Error:{0}",e);

Console.ForegroundColor = oldColor;

return false;

}

static void Main(string[] args)

{

int i = 10;

try

{

throw new TimeoutException("time out");

}

catch (Exception e) when(ConsoleLogException(e))

{

}

catch (TimeoutException e) when (i == 10)

{

}

finally

{

Console.ReadKey();

}

}

輸出結(jié)果:

上面說明一個問題,無論catch是否匹配,when都會執(zhí)行。

同樣來做一個實驗,判斷when 如果不匹配也就是沒有catch塊執(zhí)行那么會怎么樣?

static void Main(string[] args)

{

int i = 10;

try

{

throw new TimeoutException("time out");

}

catch (Exception e) when(ConsoleLogException(e))

{

}

catch (TimeoutException e) when (i == 9)

{

Console.WriteLine("enter timeoutexception");

}

finally

{

Console.ReadKey();

}

}

結(jié)果:

重新拋出異常

為什么要重新拋出異常呢?

static int GetValueFromArray(int[] array, int index)

{

try

{

return array[index];

}

catch (System.IndexOutOfRangeException ex)

{

System.ArgumentException argEx = new System.ArgumentException("Index is out of range", "index", ex);

throw argEx;

}

}

本來是要拋出IndexOutOfRangeException 改為了ArgumentException 這是為什么呢?

原因如下:用戶要調(diào)用的是我們的方法GetValueFromArray,傳入的是參數(shù),方法沒有越界這么一說,而不是一個數(shù)組,所以我們要爭對我們的目的來確定我們拋出的異常。

用戶自定義異常

自定義異常水比較深,在此只做一個簡單的介紹,單獨一節(jié)補齊。

class CostumExcetion:Exception

{

public CostumExcetion(string message) : base(message)

{

}

}

調(diào)用如下:

static void Main(string[] args)

{

int i = 10;

try

{

throw new CostumExcetion("自定義異常");

}

catch (Exception e) when(ConsoleLogException(e))

{

}

catch (CostumExcetion e) when (i == 10)

{

Console.WriteLine(e.Message);

}

finally

{

Console.ReadKey();

}

}

調(diào)用者信息

現(xiàn)在又一個需要,知道try中出現(xiàn)錯誤,但是我需要知道是那一會出現(xiàn)錯誤,這個怎么破呢?

也就是說我們希望定位到行級,那么我們就需要調(diào)用者信息了。

在異常中,我們又很多方法調(diào)用一個方法,然后在這個方法中出現(xiàn)問題,我們需要知道是怎么報錯的,到底是哪個函數(shù)調(diào)用報錯的,這時候我們需要使用查詢到調(diào)用者信息。

舉個例子:

public class CallerInformationHelper

{

public void Log([CallerLineNumber]int line = -1, [CallerFilePath] string path = null, [CallerMemberName]string name = null)

{

Console.WriteLine((line<0)?"no line":"Line"+line);

Console.WriteLine((path==null)?"No file path":path);

Console.WriteLine((name==null)?"No Member name":name);

Console.WriteLine();

}

}

調(diào)用:

CallerInformationHelper helper = new CallerInformationHelper();

helper.Log();

深圳網(wǎng)站建設www.sz886.com

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

  • 什么是異常? 異常實際上是程序中錯誤導致中斷了正常的指令流的一種事件. 異常處理的優(yōu)點: 沒有處理錯誤的程序: r...
    沉麟閱讀 588評論 0 0
  • 支持Http、Tcp和Udp的類組成了TCP/IP三層模型(請求響應層、應用協(xié)議層、傳輸層)的中間層-應用協(xié)議層,...
    moshanghuakai88閱讀 1,371評論 0 0
  • 1.靜態(tài)的using聲明 靜態(tài)的using聲明允許調(diào)用靜態(tài)方法時不使用類名: // C# 5using Syst...
    單程車票_SJ閱讀 393評論 0 1
  • 引言 我一直在探尋一個高性能的Socket客戶端代碼。以前,我使用Socket類寫了一些基于傳統(tǒng)異步編程模型的代碼...
    編程小世界閱讀 885評論 0 0
  • 一直用C#開發(fā)程序,.NET的功能越來越多,變化也挺大的,從最初的封閉,到現(xiàn)在的開源,功能不斷的增加,一直在進步。...
    編程小世界閱讀 348評論 0 1

友情鏈接更多精彩內(nèi)容