Как правильно располагать объекты, созданные с помощью LINQ - PullRequest
0 голосов
/ 23 февраля 2011

У меня есть следующий метод, который создает экземпляры одноразовых объектов.

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 следует утилизировать, когда считыватель выходит из области видимости и собирается ли мусор, правильно?

Ответы [ 2 ]

0 голосов
/ 23 февраля 2011

Dispose вызывается, когда объект оказывается мусором, что может произойти никогда или очень долго после того, как объект выпадет из области видимости. Вы должны утилизировать StringReader явно.

Если я правильно понимаю мой VB, вы можете сделать это

    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 голосов
/ 23 февраля 2011

Извините за ответ в c #.Простой способ управления IDisposables заключается в создании метода, который вызывает новый, также вызывает 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();
  }
}
...