簡體   English   中英

如何處理一次性對象拋出的異常?

[英]How to handle exceptions thrown by disposable objects?

假設Constructor和Process方法可能拋出異常,使用Disposable對象的最佳方法是什么? 我通常更喜歡以下實現之一。

  1. try-catch周圍使用塊

     try { using (Disposable dispObj = new Disposable()) { dispObj.Process(); } } catch (Exception ex) { // Do something } 
  2. 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.

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