簡體   English   中英

在C#中使用一個catch-all catch塊的finally塊是什么用的?

[英]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.

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