[英]What's the use of a finally block preceded by a catch-all catch block, in C#?
考慮以下C#代碼結構(S0-S3是任意代碼塊的占位符):
try
{
S0;
}
catch (Exception ex)
{
S1;
}
finally
{
S2;
}
S3;
在S1在catch
處理程序內拋出異常的情況下, finally
S2仍然會執行(但S3不會)。
假設S1不能拋出 ,有沒有任何一點讓S2在finally
塊內,而不是在try / catch / finally之外,就在S3之前?
try
{
// Do something that might throw
}
catch (Exception ex)
{
// Save the exception to re-throw later
// NB: This statement cannot throw an exception!
this.cachedException = ex;
}
finally
{
S2;
}
S3;
擁有finally
塊有什么意義嗎? 下面的代碼是不是等價的(嚴格假設catch
塊中的內容不能拋出):
try
{
// Do something that might throw
}
catch (Exception ex)
{
// Save the exception to re-throw later
// NB: This statement cannot throw an exception!
this.cachedException = ex;
}
// No finally block needed (?)
S2;
S3;
更新:如果接受上面的兩個代碼塊是等效的(在所假設的假設下)那么,考慮到答案中代碼清晰度的反饋,在finally
內部組合S2和S3是否優先(和等效)塊?
try
{
// Do something that might throw
}
catch (Exception ex)
{
// Save the exception to re-throw later
// NB: This statement cannot throw an exception!
this.cachedException = ex;
}
finally
{
S2; // Put S2 and S3 together inside the `finally` block to guard against
S3; // future changes in the `catch` filter, or handling code.
}
考慮到資源耗盡情況(即,內存不足),S1不能拋出的假設是脆弱的。 即使有必要(一個很大的if),對代碼的微小更改也會引入異常。
由於S2通常涉及清理和釋放有價值的資源,因此將其置於最終塊中可以清楚地傳達該意圖 。 在可能的情況下,將這些代碼放在資源擁有對象的Dispose()方法中,並用using子句替換try / finally子句,可以更好地傳達意圖(對於C#更具慣用性)。
每當您可以用兩種或更多種方式編寫內容時,請使用最清晰且最穩定的方法來更改。
第二個問題:如果涉及清理,S3應該放在finally中。 如果它預先假定try塊的成功,它應該放在finally塊之后。 如果您的catch語句沒有重新拋出,我個人會將其解釋為您已成功並可以繼續正常操作。 然而,整個'保存例外以后重新拋出'的事情讓我感到困惑。 一般來說,我建議不要在方法之外存儲重新拋出的異常。 這很不尋常,對我來說似乎很困惑。 代碼包含的意外越少,維護就越容易(包括你自己,三個月后)。
您可能不會預料到S1拋出的一種情況:如果線程被中斷,異常將自動在catch塊的末尾重新拋出。
正如Pontus所說, finally
塊表示無論發生什么,都應該始終運行此代碼。 這比捕捉一切然后繼續更清楚。
finally塊用於執行資源清理,無論是否發生異常,最后都會調用block,因此它是進行清理工作的理想場所。
請注意,即使try或catch塊包含return語句,也會執行finally子句。
我認為這類似於在語句內容中添加括號。
雖然你可以爭辯
if (x) y;
不會失敗,是什么意思說一些經驗不足的程序員以后不會出現並編輯它
if (x) y; z;
可能是這樣的情況,對於你的代碼來說,finally塊不是必需的,但是如果catch塊中的代碼發生變化,最好留下它。
if (x)
{
y;
}
總是為我贏。
在您的特定情況下,沒有區別..
但是,如果你沒有捕獲Exception,而是Exception的某個特定子類,則會有所不同。 這可能是查看try-catch-finally塊時的正常模式。
你可能能夠確保你的代碼今天沒有拋出異常,但是當你在6個月后回到它時呢? 或者其他人必須進行更改?
使用finally
塊是一種公認的模式,對任何程序員都有意義,如果你的代碼做了一些特殊和不同的事情,它會讓你或其他人絆倒。
在第二種情況下, 如果你吞下任何捕獲塊中遇到的異常 , 控制權肯定只會達到S2! Try-Catch不應該在這里使用,但要小心。
例如:
try
{
// Do something that might throw
}
catch (Exception ex)
{
// Save the exception to re-throw later
// NB: This statement cannot throw an exception!
// this.cachedException = ex;
// Must swallow any exception here to let control go further!
// If you're not sure enough [which you and me both are not likely to be] - use finally to execute S2 in any condition
}
// No finally block needed (?)
S2;
S3;
為了保證在發生異常時清理資源,請使用try / finally塊。 關閉finally子句中的資源。 使用try / finally塊可確保即使發生異常也會處置資源....有關詳細信息,請訪問http://itpian.com/Coding/5143-Need-for-Finally-block.aspx
不,你不必使用它。 在這種情況下不需要它。 它是您的選擇,取決於您可能/可能不會使用的資源。 如果您需要清理可能擁有的任何資源,那么finally塊是最佳選擇。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.