2013-05-20 65 views
7

當我運行代碼分析工具,我得到如下:CA2000:Microsoft.Reliability:對對象調用System.IDisposable.Dispose「DT」之前,所有引用超出範圍

警告1個CA2000: Microsoft.Reliability:在'Class1.test.testMethod()'方法中,對象'dt'不是沿着所有異常路徑處理的。在所有對它的引用超出範圍之前,調用System.IDisposable.Dispose對象'dt'。 如何解決警告?

public void testMethod() 
{ 
    DataTable dt = new DataTable(); 
    DataTable dt1= new DataTable(); 
     try 
     { 
     if (dt.Rows.Count == 0) 
     { 
      dt1.Merge(dt); 
     } 
     } 
     catch 
     { 
     throw; 
     } 
     finally 
     { 
     if (dt != null) dt.Dispose(); 
     if (dt1 != null) dt1.Dispose(); 
     } 
} 
+0

'object'dt'沒有沿着所有異常路徑放置我認爲編譯器實際上是在抱怨空的catch塊,但是使用using語句(比如當前評分最高的答案)應該是最好的做法,那麼你甚至不需要調用dispose。編輯:+1因爲警告而煩惱。 – Izzy

回答

5

真的不知道爲什麼你得到這個錯誤,但你可以嘗試using語句塊在你的方法,看看錯誤消失。嘗試這樣的:

public void testMethod() 
{ 
    using (DataTable dt = new DataTable()) 
    using (DataView dv = new DataView(dt)) 
    { 
     //your work 
    } 
} 
+0

是的,對不起 - 我注意到,我發佈後 - 我刪除了評論和downvote。你的語法絕對比OP更受歡迎,但你確實錯過了錯誤發生的原因。 –

+0

@DanPuzey,在我的機器上缺少工具,否則我會證實,但仍然,我的猜測是實例化是在try塊之外完成的。 – Habib

+0

@saliqueahmad,不客氣,是否解決了警告? – Habib

2

Dispose objects before losing scope

如果一次性對象未明確設置之前所有 對它的引用超出範圍,對象會在某個 不確定的時間來佈置時,垃圾收集器運行該對象的終結器 。由於可能發生的異常事件會阻止對象運行的終結器 ,因此該對象應該是 而不是。

若要解決違反此規則的問題,請在對象的所有引用超出範圍之前先調用System.IDisposable.Dispose, 。

請注意,您可以使用using語句(在Visual Basic中使用)到 實現IDisposable的換行對象。以這種 方式包裝的對象將自動放置在使用塊的結尾處。

using (DataTable dt = new DataTable()) 
using (DataView dv = new DataView(dt)) 
{ 

} 
0

大概是因爲DataTable的初始化理論上可能脫手打破之前。您可以嘗試使用null初始化它,並使用新的DataTable實例在try塊內進行初始化。畢竟終於可以進行可空測試了。

喜歡的東西

public class Class1 
{ 
    public class test 
    { 
     public void testMethod() 
     { 
      DataTable dt = null; 

     try 
     { 
      dt = new DataTable(); 

     } 
     catch 
     { } 
     finally 
     { 
      if (dt != null) dt.Dispose(); 
     } 
    } 
    } 
} 
+0

你已經完全移除了'dv'的聲明 - 你的代碼不會編譯! –

+0

我不明白倒票。我的觀點是在上面的評論中,我寫錯了什麼?我刪除了代碼的一些部分,以僅使用dt變量創建一個點。 – alexb

+0

你的代碼不能編譯;我不認爲這是一個有用的答案。 –

1

我懷疑錯誤發生,因爲你是創建兩個DataView s,而只有其中一人將永遠不會設置:您初始化dv到一個新的DataView,然後分配另一個在try塊。當您點擊finally時,初始作業中的一個不會被處理,因爲您不會參考它。

修改你的宣言DataView dv = new DataView()只是聲明變量,而不是初始化它:

public void testMethod() 
{ 
    DataTable dt = new DataTable(); 
    DataView dv = null; 

    try 
    { 
     dv = new DataView(dt); 
    } 
    finally 
    { 
     if (dt != null) dt.Dispose(); 
     if (dv != null) dv.Dispose(); 
    } 
} 

注意:這直接解決您的第二個錯誤消息(約dv),並間接解決了第一個(約dt )。第一個錯誤是因爲,如果dv的冗餘初始化拋出異常,dt將不會被處置 - 因此刪除初始化可修復錯誤。

+0

錯誤是關於「dt」變量,而不是關於修復指出的「dv」。無論如何,+1的嘗試。 – alexb

+0

看起來修復的解釋與我的相似,而你也受到了相同的懲罰。從技術上講,你是對的,但我認爲你把它們從字面上理解了。 – alexb

+0

每個人都有一個錯誤。我將編輯以解釋爲什麼我的代碼更改修復了這兩個問題。 –

2

在代碼的第7行中,您創建了一個未使用的虛擬DataTable。編譯器正在抱怨DataTable和DataView對象。改變下面的代碼,它會工作。

public class Class1 
{ 
    public class test 
    { 
     public void testMethod() 
     { 
      DataTable dt = null; 
      DataView dv = null; 


     try 
     { 
      // dt must be assigned a value only within the try block 
      dt = new DataTable(dt); 
      dv = new DataView(dt); 
     } 
     catch 
     { } 
     finally 
     { 
      if (dt != null) dt.Dispose(); 
      if (dv != null) dv.Dispose(); 

     } 
     } 
    } 
} 

更新

如果處置都dtdv你會得到CA2202 error。這是因爲dt正在處理兩次。一次處置dt並一次處置dv。爲了避免這種情況,您必須在try/catch塊的末尾分配nulldt

try 
    { 
     dt = new DataTable(dt); 
     dv = new DataView(dt); 
     dt=null; 
    } 
+0

不,你已經清空了兩個對象,現在代碼會失敗,因爲'dt'是'null'。你只需要'dv'即可。 –

+0

感謝Manoj將它初始化爲null.Warnings被刪除。 –

+0

@salique,你可以接受或提出幫助你的答案 – alexb

0

發生是因爲您正在初始化try塊外的dt。

public void testMethod() 
{ 
    DataTable dt = null; 
    DataView dv = null; 
    try 
    { 
     dt = new DataTable(); 
     dv = new DataView(dt); 
    } 
    catch 
    { 
    } 
    finally 
    { 
     if (dt != null) dt.Dispose(); 
     if (dv != null) dv.Dispose(); 
    } 
} 

}

在其他的答案,你也可以使用塊使用,而不是嘗試......最後說。

public void testMethod() 
{ 
    using (DataTable dt = new DataTable()) 
    { 
     using (DataTable dv = new DataView(dt)) 
     { 
     } 
    } 
} 

一個問題:是不是你打算讓test類嵌套類的Class1

0
public class test 
    { 
     public void testMethod() 
     { 
      DataTable dt = null; 
      DataView dv = null; 


     try 
     { 
      dv = new DataView(dt); 
     } 
     catch 
     { } 
     finally 
     { 
      if (dt != null) dt.Dispose(); 
      if (dv != null) dv.Dispose(); 

     } 
     } 
    } 
} 
+0

上面的代碼爲我工作。謝謝所有你的迴應。 –

1

您的示例代碼演示的確切內容尚不清楚。

但是,如果您嘗試按照MSDN推薦的模式清除CA2000上的誤報,那麼有一些已知的補救措施。我大略2案件here,其中一個簡單的代碼更改使代碼分析識別推薦模式:

  1. 臨時必須命名爲字符串「臨時」在駝峯前置到最終目的地IDisposable
  2. 最終目的地IDisposable必須是函數的返回值。
相關問題