2013-04-05 50 views
4

我有一個函數(請參閱下面的代碼片段)。我無法獲取代碼分析規則CA2202固定

我啓用了代碼分析功能,並且違反了CA2202規則。

編輯:我添加的pdfStamper收盤否則PDF會損壞)

CA2202:多次

的方法實現包含的代碼路徑可能導致不處置的對象對同一對象多次調用IDisposable.Dispose或Dispose等價物(如某些類型的Close()方法)。

在CA2202 MSDN頁面(here)中,建議的修復程序不起作用。

如何重寫代碼而不必抑制這種違規行爲?

private byte[] DoGenerateFinishedGamePdf(int gameSessionLogId) 
{ 
    var finishedGameCertificatePdfFile = httpServerUtilityWrapper.MapPath(ConfigurationManager.AppSettings["FinishedGameCertificateFile"]); 

    var pdfReader = new PdfReader(finishedGameCertificatePdfFile); // note that PdfReader is not IDisposeable 

    using (MemoryStream memoryStream = new MemoryStream()) 
    using (PdfStamper pdfStamper = new PdfStamper(pdfReader, memoryStream)) 
    { 
     var fields = pdfStamper.AcroFields; 
     fields.SetField("CityName", "It works!"); 

     pdfReader.Close(); 

     pdfStamper.FormFlattening = true; 
     pdfStamper.FreeTextFlattening = true; 
     pdfStamper.Close(); 

     return memoryStream.ToArray(); 
    } 
} 
+0

這很奇怪。我使用一次性對象,我從來沒有收到處置警告。你正在收到這個memoryStream或pdfStamper? – 2013-04-05 11:31:10

回答

1

啊,大家最喜歡的警告!在這種情況下MemoryStream.Dispose是冪等(目前什麼都不做),所以它不是一個真正的問題,但是在「修復」如下:

MemoryStream memoryStream = null; 
try 
{ 
    memoryStream = new MemoryStream(); 
    using (PdfStamper pdfStamper = new PdfStamper(pdfReader, memoryStream)) 
    { 
    memoryStream = null; 

    var fields = pdfStamper.AcroFields; 
    fields.SetField("CityName", "It works!"); 

    pdfReader.Close(); 

    pdfStamper.FormFlattening = true; 
    pdfStamper.FreeTextFlattening = true; 
    pdfStamper.Close(); 

    return memoryStream.ToArray(); 
    } 
} 
finally 
{ 
    if (memoryStream != null) memoryStream.Dispose(); 
} 

由於PdfStamper「擁有」將MemoryStream將處置當PdfStamper.Dispose被調用時,所以我們只需要在MemoryStream上調用Dispose,如果我們不處理PdfStamper,只有在PdfStamper的構造失敗時纔會發生。

+0

由於您重新聲明瞭內存流,因此代碼段將無法編譯。如果我通過刪除typename來解決這個問題,我會在第5行得到一個CA2000錯誤:'在對象'memoryStream'中調用System.IDisposable.Dispose之前,所有對它的引用超出範圍'... – 2013-04-05 10:27:53

+0

@PatrickPeters對於非 - 編譯,複製粘貼錯誤,答案更新。嗯,上面的代碼在我的VS(VS2012使用.Net 4.5編譯器)沒有警告 – 2013-04-05 10:59:12

+0

我忘了從你的代碼示例在我的代碼中放置pdfStamper = new PdfStamper(pdfReader,memoryStream),現在我得到3(!!)警告:在創建memoryStream時創建一個CA2000,在finally塊中的每個Dispose中創建兩個CA2202 ...請注意,我編輯了原始問題,在pdfStamper完成後添加了一行代碼行工作。 – 2013-04-05 11:07:45

1

發生這種情況是因爲PdfStamper即使不應該放置流。它沒有創建它,也沒有它,所以它沒有業務處理它。

你的代碼確實創建了流,它擁有它,所以它應該處理它是很自然的。如果PdfStamper不是不恰當地處理流,那麼所有嵌套使用都可以。

您的第一個舉動應該是提交一個錯誤報告/功能請求,說明該流的PdfStamper部署被刪除或至少可以避免。一旦你這樣做了,你可以安全地抑制CA2202違規,因爲MemoryStream的雙重處置不會產生有害的後果。

順便說一句,PdfStamper.Dispose()調用PdfStamper.Close()(至少在版本5.4.0),所以你應該能夠刪除PdfStamper.Close()調用。

相關問題