2012-06-28 30 views
14

通常在廢棄的私有成員,你不妨做到以下幾點:告訴FxCop的另一種方法是調用dispose

public void Dispose() { 
    var localInst = this.privateMember; 
    if (localInst != null) { 
     localInst.Dispose(); 
    } 
} 

當地作業的目的是爲了避免出現競爭狀況,其中另一個線程可以分配私有成員在空檢查後爲空。在這種情況下,我不在乎Dispose在實例上被調用兩次。

我使用這個模式所有的時間,所以我寫了一個擴展的方法來做到這一點:

public static void SafeDispose(this IDisposable disposable) 
{ 
    if (disposable != null) 
    { 
     // We also know disposable cannot be null here, 
     // even if the original reference is null. 
     disposable.Dispose(); 
    } 
} 
在我的課

而現在,我可以做到這一點:

public void Dispose() { 
    this.privateMember.SafeDispose(); 
} 

問題是, FxCop不知道我在做這件事,它在每種情況下都會給我提供CA2000: Dispose objects before losing scope警告。

我不想關閉這條規則,我不想壓制每一種情況。有沒有辦法暗示FxCop這個方法相當於Dispose就它而言?

+3

您樣品說'this.privateMember.Dispose()'。你的代碼實際上是否說'this.privateMember.SafeDispose()'? –

回答

8

簡短的回答是:沒有辦法來暗示該對象被佈置在別處。

有點反射(或dotPeek-ing,或其他)解釋了原因。

FxCop在C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop。 (針對您的OS/VS版本組合進行相應調整。)規則位於Rules子目錄中。

在主FxCop文件夾,開放

  • Microsoft.VisualStudio.CodeAnalysis.dll
  • Microsoft.VisualStudio.CodeAnalysis.Phoenix.dll
  • phx.dll

Rules文件夾,開放DataflowRules.dll

DataflowRules.dll找到Phoenix.CodeAnalysis.DataflowRules.DisposeObjectsBeforeLosingScope。這是評估的實際課程。

看看那裏的代碼,你可以看到兩個關於你的問題感興趣的東西。

  1. 它採用共享服務稱爲SharedNeedsDisposedAnalysis
  2. It 派生自FunctionBodyRule

的第一項是有趣的,因爲SharedNeedsDisposedAnalysis是什麼決定了哪些符號需要Dispose()調用。它非常全面,通過代碼「走路」來確定需要處理什麼以及實際處理的內容。然後它保留這些東西的表格供以後使用。

第二項很有趣,因爲FunctionBodyRule規則評估單個函數的主體。還有其他規則類型,如FunctionCallRule,它們評估諸如函數調用成員之類的東西(例如,ProvideCorrectArgumentsToFormattingMethods)。

的觀點是,在SharedNeedsDisposedAnalysis服務潛在的「小姐」在那裏它可能無法通過你的方法遞歸地看到,事情確實越來越佈置和FunctionBodyRule不會超越函數體的限制之間,它只是不抓住你的擴展。

這是一樣的道理「保護功能」像你使用它之前永遠不會被視爲驗證參數 - FxCop的仍然會告訴你檢查空的說法,即使那是什麼「保護功能」是做。

基本上有兩種選擇。

  1. 排除問題或關閉規則。它沒有辦法做到你想要的。
  2. 創建一個將瞭解擴展方法的自定義/派生規則。使用您的自定義規則代替默認規則。

其編寫的自定義規則的FxCop我之後,我會讓你知道,我發現它... 不平凡。如果你真的走上了這條路,而世界上的建議是使用新的Phoenix引擎規則風格(這是目前的​​使用的風格),我發現它更容易理解舊版/標準FxCop SDK規則(請參閱FxCopSdk.dll主FxCop文件夾)。反射器將是一個巨大的幫助,找出如何做到這一點,因爲它幾乎沒有文檔。查看Rules文件夾中的其他程序集以查看這些文件的示例。

+1

實際上,CA1062有一種識別防護功能的機制:具有名爲ValidatedNotNullAttribute的屬性的裝飾。不幸的是,處理規則沒有類似的機制。 –

+0

謝謝特拉維斯!你知道編寫自定義規則的好指南嗎?我將fxcop作爲構建的一部分運行,我想確保它可以從源代碼(而不是程序文件)加載規則。 – Haacked

+0

我發現[this](http://www.binarycoder.net/fxcop/pdf/fxcop.pdf)白皮書非常有用。 – riezebosch

1

我絕不是FxCop的專家,但是this question關於使用SuppressMessage的答案呢?我不知道使用SuppressMessage屬性裝飾SafeDispose方法是否會導致FxCop在分析調用它的方法時抑制該消息,但似乎值得一試。

不要相信下面的語法,但類似:

[SuppressMessage("Microsoft.Design", "CA2000:Dispose objects before losing scope", Justification = "We just log the exception and return an HTTP code")] 
public static void SafeDispose(this IDisposable disposable) 
0

由於Travis概述的所有原因,此代碼分析規則是一個有問題的規則。它似乎排隊等待任何「新」操作,並且除非處理呼叫接近,否則CA2000觸發。

而不是使用新的,請撥打本方法在人體:

MyDisposableClass result; 
MyDisposableClass temp = null; 
try 
{ 
    temp = new MyDisposableClass(); 
    //do any initialization here 
    result = temp; 
    temp = null; 
} 
finally 
{ 
    if (temp != null) temp.Dispose(); 
} 
return result; 

這樣做是刪除使物體不可達處置初始化的任何可能性。在你的情況下,當你「新建」私人會員時,你可以在一個類似上述方法的方法中進行。使用這種模式後,你當然仍然對正確的處理負責,你的擴展方法是推廣空檢查的好方法。

我發現你可以避免使用CA2000,同時仍然傳遞IDisposables並做他們想做的事情 - 只要你在上面的方法中正確地創建它們。試試看,讓我知道它是否適合你。祝你好運,好問題!

此規則(包括本)其他修復羅列如下:CA2000: Dispose objects before losing scope (Microsoft)

相關問題