簡體   English   中英

C#中的3個catch塊變體之間有什么區別('Catch','Catch(Exception)'和'Catch(Exception e)')?

[英]What is the difference between the 3 catch block variants in C# ( 'Catch', 'Catch (Exception)', and 'Catch(Exception e)' )?

在C#中,'Catch','Catch(Exception)'和'Catch(Exception e)'之間有什么區別?

關於try-catchMSDN文章在其示例中使用了其中的兩篇,但沒有解釋使用目的的差異。

try
{}
catch 
{}

try 
{}
catch (Exception)
{}

try
{}
catch(Exception e)
{}

這些有何不同? 哪些會捕獲所有異常,哪些異常捕獲?

還沒有人提到這個問題的歷史方面。

在.NET中,拋出一個不是從Exception派生的對象是合法的。 (它在C#中不合法,但它在其他一些托管語言中。)許多人不知道這個事實,但它是合法的。 由於這很瘋狂 ,在.NET 2.0中默認值已經改變:如果你試圖拋出一些不是異常的東西,那么它會自動包裝在RuntimeWrappedException類中,這顯然一個例外。 然后扔掉那個對象。

由於這種奇怪的原因,在C#1.0中,通常會看到同時執行這兩種操作的代碼:

try
{ do something }
catch(Exception) 
{ handle the exception }
catch
{ handle the thrown non-exception }

事實上,存在安全性和正確性問題; 在某些情況下,出於安全原因,你必須捕獲任何拋出的東西(可能重新拋出它),人們會合理地認為catch(Exception)捕獲了所有東西,但事實並非如此。

幸運的是,自.NET 2.0以來,事情變得更加明智; 您可以依賴catch {}catch(Exception) {}catch(Exception ex) {}來捕獲所有需要的東西。

最后:如果出於某些瘋狂的原因你想要打開C#1.0行為,你可以放

[assembly:System.Runtime.CompilerServices.RuntimeCompatibility(WrapNonExceptionThrows = false)]

在你的程序中。

簡而言之...

沒有參數的Catch將收到任何異常,但沒有辦法解決它。

Catch (Exception)基本上會做同樣的事情,因為你已經指定了根Exception類型。 Catch (IOException)相反,它只捕獲IOException類型。

Catch (Exception ex)捕獲所有異常並提供通過ex變量解決它的方法。

閱讀更多: http//msdn.microsoft.com/en-us/library/ms173160.aspx

第一個版本捕獲從Exception類派生的所有異常。

第二個版本捕獲指定的異常。

第三個版本捕獲具有聲明名稱的指定異常。 然后在catch塊中,您可以使用此對象,例如,查看完整的錯誤: e.ToString();

在這里閱讀更多。

所有這些都基本相同,不同之處在於它們提供的有關錯誤的信息量。

catch (foo ex) {}將過濾掉所有異常,除了那些可以強制轉換為foo類型的異常。 它還為您提供了錯誤的實例供您使用。

catch (foo) {}與上面的相同,但它不會為您提供異常的實例。 您將知道異常的類型,但無法從中讀取信息。

請注意,在這兩種情況下,如果異常的類型是Exception ,它們將捕獲所有異常。

catch {}捕獲所有異常。 您不知道它捕獲的類型,您無法訪問該實例。

您可以根據捕獲異常所需的信息來選擇使用哪一個。

無論您使用哪一個,都可以使用命令throw;傳遞捕獲的異常throw; (沒有參數)。

在你的例子中,什么都沒有,因為你沒有做任何異常的事情。 但要澄清......

  • 這會抓住一切,但除了例外之外什么也不做。

     catch {} 

    這僅在您想要保證從方法返回時才有用。

  • 這只捕獲Exception類型的Exception (這是一切)但對異常沒有任何作用。

     catch (Exception) {} 

    如果要通過指定要處理的類型來限制捕獲的異常類型,這將非常有用。 任何其他異常都會冒出調用堆棧,直到找到合適的處理程序。

  • 這只捕獲Exception類型的Exception (這是一切)並且可以對異常執行某些操作,但碰巧什么都不做

     catch (Exception ex) {} 

    這種技術為您提供了更多選擇。 您可以記錄異常,檢查InnerException等。再次,您可以指定要處理的異常類型。

除非你以某種方式重新拋出異常,否則所有這些都是不好的做法。 一般情況下,您應該只捕獲可以有意義處理的異常,並允許其他任何事情冒泡。

添加catch(Exception e)將允許您訪問Exception對象,該對象包含有關拋出的異常的詳細信息,例如Message和StackTrace; 記錄此信息以幫助診斷錯誤很有用。 如果沒有聲明您嘗試捕獲的異常,那么一個簡單的catch就不會讓您訪問異常對象。

此外,捕獲基本異常通常被認為是不好的做法,因為它太過於通用,並且在可能的情況下,您應該首先考慮特定的異常。 例如,如果您正在使用文件,則可以考慮以下try / catch塊:

try{
    //open your file and read/write from it here
}catch(FileNotFoundException fe){
    //log the message
    Log(fe.Message);
}catch(Exception e){
    //you can catch a general exception at the end if you must
}finally{
    //close your file
}

在最高級別,他們都是一樣的; 他們都抓住了例外。

但是要進一步向下鑽取,在第一種情況下,您正在捕獲異常並且不執行任何操作(您沒有定義的類型)。 在第二個示例中,您將捕獲異常類型的異常。 在上一個示例中,您將捕獲與示例2中相同的異常類型,但現在您將異常放入一個允許您在MessageBox中顯示它的變量或:

e.Message

重要的是要注意異常是分層意義,如果您在同一個try / catch塊中捕獲多種類型的異常,則從最具體的異常類型轉到最常規異常類型。 像這樣:

try {
}
catch (SqlException sqlExc) {
}
catch (Exception exc) {
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM