[英]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-catch的MSDN文章在其示例中使用了其中的兩篇,但沒有解釋使用目的的差異。
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.