2012-03-30 12 views
11

¿Tengo que ajustar todos mis objetos IDisposable en las declaraciones using(){}, incluso si solo estoy pasando uno al otro? Por ejemplo, en el siguiente método:¿Es necesario anidar objetos con objetos IDisposable?

public static string ReadResponse(HttpWebResponse response) 
{ 
    string resp = null; 
    using (Stream responseStream = response.GetResponseStream()) 
    { 
     using (StreamReader responseReader = new StreamReader(responseStream)) 
     { 
      resp = responseReader.ReadToEnd(); 
     } 
    } 
    return resp; 
} 

¿Podría consolidar esta a un solo using así:

public static string ReadResponse(HttpWebResponse response) 
{ 
    string resp = null; 
    using (StreamReader reader = new StreamReader(response.GetResponseStream())) 
    { 
     resp = reader.ReadToEnd(); 
    } 
    return resp; 
} 

¿Puedo contar tanto el Stream y la StreamReader está dispuesto? ¿O tengo que usar dos declaraciones using?

Respuesta

12

Sí, se puede, pero eso es porque la documentación constructor StreamReader específicamente dice: "El objeto StreamReader llama a Dispose en el objeto Stream proporciona cuando se llama StreamReader.Dispose"

Si no lo hizo, entonces podría hacer algo como esto para al menos limpiar el código un poco.

using (Stream responseStream = response.GetResponseStream()) 
using (StreamReader responseReader = new StreamReader(responseStream)) 
{ 
    resp = responseReader.ReadToEnd(); 
} 
+0

Me encanta usar apilamientos, mucho más limpio que las indentaciones masivas :-) –

+0

Piense en las llaves como opcionales. De la misma manera que lo son con cualquier otra declaración, como una declaración 'if'. Es un código válido para escribir "if (expresión) if (expresión2) if (expresión3) {/ * Múltiples líneas de código.* /} "donde cada declaración if está anidada dentro de la anterior. –

+0

@Moozhe No es tan sorprendente que se compile, es más cómo maneja VS la sangría. Cuando usas corchetes, lo pestañas en un nivel extra, cuando lo haces esto no es así. Si al hacer esta tabulación en un nivel probablemente ni siquiera lo use. – Servy

2

Me encontraron esta cuestión más amplia que la simple cuestión de anidación using comunicado, se trata de un problema de diseño de la aplicación bastante interesante.

¿Tengo que envuelva todos mis objetos IDisposable en el uso) {} (declaraciones, incluso si sólo estoy pasando uno a otro?

Sí, ya que están crear instancias de objeto que implementa IDisposable - que son conscientes de que la eliminación, o bien envolviendo en using() o explícita Dispose() llamada.

razón detrás de esto es simple, imagina siguiente escenario: usted tiene siguientes entidades

  • Transportservice
  • ReportService
  • FeedService

todos los implementos IDisposable. Tanto ReportService como FeedService requieren una instancia de TransportService para pasar durante la etapa de construcción. Y pregunta: ¿es correcto desechar TransportService en el Dispose() de ReportService o FeedService? ¡No! En Becuause, la misma instancia de servicio de transporte podría aprobarse en ambos servicios y una vez que uno de los dos se transporte, esto afectará también a todos los servicios.

public sealed class ReportService : IDisposable 
{  
    private readonly ITransportService transportService; 

    public ReportService(ITransportService transportService) 
    { 
     this.transportService = transportService; 
    } 

    public Dispose() 
    { 
     // ReportService should not dispose objects 
     // passed in since they could be used by other classes as well 
     // DO NOT: transportService.Dispose(); 
    } 
} 
+1

No es realmente una pregunta de "siempre deshacerse" o "nunca deshacerse". Hay dos caminos: cuando pasas un objeto desechable para otro que ya no eres responsable de deshacerse de él, y lo que sea que lo pasen se asegurará de que esté dispuesto. Eso es lo que está sucediendo aquí. Cuando pasas un stream a un streamreader estás diciendo, "lidias con esto stream ". Si le está dando un objeto desechable a otra persona pero dice:" Todavía soy responsable de deshacerse de esto, su alcance es más grande que el suyo "entonces ni siquiera necesita implementar IDisposable lo que le pasa. – Servy

+0

Verás muchas exa Mples de este último con DataContexts. Es posible que tenga un método/clase de ayuda que toma una instancia de un DataContext y ni siquiera es desechable. no se deshará del DataContext, sabe que quien le haya entregado el DataContext se encargará de limpiarlo y garantizar que no se elimine mientras lo estoy usando. – Servy

3

La persona/código/capa que creó el objeto desechable debería en general ser responsable de la eliminación del objeto. Sin embargo, hay escenarios que podría tener cuando este no es el caso y eso está bien. Se convierte entonces en un problema de documentación.

Cuestiones relacionadas