2011-02-23 36 views
0

我有以下創建一次性對象實例的方法。如何正確處理用LINQ創建的對象

Public Overridable Sub TransformXmlDocumentsToFileStream(ByVal stream As System.IO.Stream, ByVal xmlDocuments As IEnumerable(Of String), ByVal transformContext As XslTransformContext) 
    Dim readers As IEnumerable(Of XmlReader) = _ 
     (From document In xmlDocuments _ 
     Select XmlReader.Create(New System.IO.StringReader(document))) 

    With transformContext 
     TransformXmlDocumentsToFileStream(stream, readers, transformContext) 
    End With 
End Sub 

然後我遍歷對象在另一種方法中:

For Each reader In readers 
    Using reader 
     transform.Transform(reader, writer) 
    End Using 
Next 

在Visual Studio代碼分析器被給予警告:

CA2000:Microsoft.Reliability:在方法「TransformHelper .TransformXmlDocumentsToFileStream(Stream,IEnumerable(Of String),XslTransformContext)',對象'New StringReader(document)'不會沿着所有異常路徑放置。調用System.IDisposable.Dispose在對象'New StringReader(document)'之前,所有對它的引用超出範圍。

由於沒有對StringReader沒有提到,我不能把它在使用塊或以其他方式處置它。可以忽略這個警告嗎? StringReader應該在讀者超出範圍並被垃圾收集時處理,是否正確?

+0

在這種特殊情況下我的VB權,讀者可以在使用塊內關閉,從而關閉底層流。 – 2011-02-24 20:07:05

回答

0

對不起,在C#中的答案。管理IDisposables的一個簡單方法是使調用new的方法也調用Dispose。

List<StringReader> stringReaders = new List<StringReader>(); 
    //note: Select is deferred. stringReaders is captured. 
IEnumerable<XmlReader> readers = 
    xmlDocuments.Select(document => 
    { 
    StringReader sr = new System.IO.StringReader(document); 
    stringReaders.Add(sr); 
    return XmlReader.Create(sr); 
    }); 
try 
{ 
    //this method enumerates readers, causing all of the allocations. 
    TransformXmlDocumentsToFileStream(stream, readers, transformContext); 
} 
finally 
{ 
    foreach(StringReader x in stringReaders) 
    { 
    x.Dispose(); 
    } 
} 
+0

不用擔心C#,我很瞭解它。我希望我可以在我的環境中使用它。這太糟糕了,它們不是一個可以被吸引的事件(OnSelect或OnEnumerate),因此可以在迭代過程中進行處置。感謝您的解決方案。 – 2011-02-24 18:36:03

0

Dispose當對象恰好是垃圾回收,這可能是沒有或對象之後很長一段時間超出範圍時調用。您應該明確地處理您的StringReader

如果我讓你可以像這樣

Dim stringReaders As IEnumerable(Of System.IO.StringReader) = _ 
     (From document In xmlDocuments _ 
     Select New System.IO.StringReader(document)).ToList() 

    Try 
     Dim readers As IEnumerable(Of XmlReader) = _ 
      (From stringReader In stringReaders _ 
      Select XmlReader.Create(stringReader)) 
     With transformContext 
      TransformXmlDocumentsToFileStream(stream, readers, transformContext) 
     End With 

    Finally 
     For Each stringReader In stringReaders 
      stringReader.Dispose() 
     Next 
    End Try 
+0

我可能在這裏是錯誤的,但不會最終你建議重新創建所有的字符串讀者,因爲這是第二次遍歷枚舉?我相信@David B的解決方案通過將讀者存儲在單獨的列表中來排除這種情況。 – 2011-02-24 18:30:27

+0

@Richard,不,''.ToList()'確保創建只執行一次。 – 2011-02-24 18:48:32

+0

啊,對不起。我沒有看到這一點,也沒有考慮這個問題,因爲我特意試圖不這樣做。在這種情況下,xmlDocuments本身就是另一個DataReader的IQueryable(我爲DataReader編寫了一個IEnumerable/IEnumerator包裝器)。我不想一次將所有文檔都放在列表中,這樣我就不會分配一大塊內存。 – 2011-02-25 15:55:18