[英]How to handle exceptions thrown by disposable objects?
假設Constructor和Process方法可能拋出異常,使用Disposable對象的最佳方法是什么? 我通常更喜歡以下實現之一。
try-catch周圍使用塊
try { using (Disposable dispObj = new Disposable()) { dispObj.Process(); } } catch (Exception ex) { // Do something }
try-catch-finally塊。
Disposable dispObj2 = null; try { dispObj2 = new Disposable(); dispObj2.Process(); } catch (Exception ex) { // Do something } finally { if (dispObj2 != null) { dispObj2.Dispose(); } }
更新:
再說一遍: “假設Constuctor和Process方法可能拋出異常” 。 我真的不明白為什么沒有人關心他們答案中的異常。
using
很好。 它有一個內置的try-finally塊。 如果發生異常,則自動調用dispose方法。
這可以
using (Disposable dispObj = new Disposable())
{
dispObj.Process();
}
像這樣做:
using (Disposable dispObj = new Disposable())
{
dispObj.Process();
}
一次性對象在超出using
子句的范圍時總是處理掉,即使它是異常的。
並且不要使用空catch {}
,完全沒有意義。
using語句在后台使用try - finally,僅適用於實現IDisposable的對象。 您不必在使用時使用try catch。 請看以下示例(來自MSDN - using語句 )。
using (Font font1 = new Font("Arial", 10.0f))
{
byte charset = font1.GdiCharSet;
}
以上代碼與:
Font font1 = new Font("Arial", 10.0f);
try
{
byte charset = font1.GdiCharSet;
}
finally
{
if (font1 != null)
((IDisposable)font1).Dispose();
}
using (Disposable dispObj = new Disposable())
{
dispObj.Process();
}
}
實現IDisposable接口的類通常使用.NET框架垃圾收集器無法清除的資源。 調用IDisposable.Dispose()方法可以執行將寶貴資源顯式釋放回世界的代碼。 實現IDisposable接口的類的一個主要示例是SqlConnection類。 SqlConnection類使用Microsoft SQL Server數據庫連接。 由於SQL Server支持有限數量的連接,因此盡快釋放連接非常重要。 通常,您不直接調用Dispose()方法。 通常,您可以像在代碼中提到的那樣利用代碼中的Using語句
在可能的情況下,您應該使用using塊。 它將保證在您的對象上調用Dispose。 手動執行此操作容易出錯。
using (IDisposable disp = new IDisposable())
{
//some logic here
}
此代碼將翻譯成以下內容:
IDisposable disp = new IDisposable();
try
{
//some logic here
}
finally
{
if (disp != null)
((IDisposable)disp).Dispose();
}
塊“finally”中的代碼始終執行,因此它為您提供了拋出異常的可能性,使用塊返回,而不會懷疑Dispose不會被調用。
但是你應該小心使用和對象初始化器。
using (var fs = new FileStream(@"C:\blabla", FileMode.Open) { Position = pos })
{
//some logic here
}
從這里你可以看到屬性Position可以拋出異常。 問題是該對象將被創建,這將在try塊中完成 ,因此可能存在內存泄漏。 正確的方法
using (var fs = new FileStream(@"C:\blabla", FileMode.Open))
{
fs.Position = pos;
//some logic here
}
您提出的方法#1可能是實現您想要的最簡潔的方法。
周圍的try
... catch
塊應該捕獲拋出的任何異常,包括構造函數拋出的異常。 如果在使用一次性物體時(在using
塊內)發生異常,則物體也將在catch
接管之前被丟棄。
方法#2采用方法#1的不同執行路徑。 請注意,根據C#Reference ,方法#1按字面編譯,就好像編寫了以下內容:
try
{
{
Disposable dispObj = new Disposable();
try
{
dispObj.Process();
}
finally
{
if (dispObj != null)
((IDisposable)dispObj).Dispose();
}
}
}
catch (Exception ex)
{
// Do something
}
因此,兩種方法之間的范圍是不同的。 在可能的情況下,我更喜歡方法#1,因為范圍問題,也因為它更容易閱讀。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.