2010-07-09 13 views
5

Tengo una pregunta estúpida, pero quiero escuchar a la comunidad aquí.Eliminación de recursos en .NET

Así que aquí es mi código:

using (FtpWebResponse response = (FtpWebResponse)request.GetResponse()) 
{ 
     return true; 
} 

Mi pregunta, ¿es diferente de:

(FtpWebResponse)request.GetResponse(); 
return true; 

¿Cuál es mejor en general? cuál en términos de GC y por qué?

+0

Creo que ustedes no entendieron el punto aquí: Como puede ver en la segunda opción, debería escribirlo así: request.GetResponse(); return true; Como puede ver, no me importa qué en la devolución GetResponse y lo ignoro por completo. En cuanto a la funcionalidad de uso, soy totalmente consciente de ello, no estaba seguro de si hay algún beneficio adicional de agregar el uso aquí en puede ni siquiera preocuparse por la respuesta. Espero haberlo aclarado. –

+4

@Or A: Ya sea que le importe la respuesta o no, todavía está llamando a 'GetResponse', lo que significa que el objeto devuelto aún debe eliminarse. (Y el patrón recomendado para hacer eso normalmente sería un bloque 'using'.) – LukeH

+0

@LukeH: En este extraño contexto, el uso de' .Dispose(); 'probablemente sea correcto. –

Respuesta

11

La primera es mejor, pero no en términos de GC. WebResponse implementa IDisposable porque tiene recursos que deben liberarse, como conexiones de red, flujos de memoria, etc. IDisposable está en su lugar porque usted, como consumidor, sabe cuándo ha terminado con el objeto y llama al Dispose al notifique el clase ya ha terminado, y es libre de limpiarlo.

El patrón using realmente solo llama a Dispose debajo del capó. P.ej. su primer ejemplo se compila para ser esto:

FtpWebResponse response = (FtpWebResponse)request.GetResponse() 
try 
{ 
} 
finally 
{ 
    ((IDisposable)response).Dispose(); 
} 
return true; 

Esto está separado del recolector de basura. Una clase también podría limpiar los recursos en el finalizador, la cual es llamada de GC, pero no se debe confiar en que para suceder por dos razones:

  1. Podría ser un tiempo muy largo antes de GC, finalmente, vuelve, que significa que esos recursos están allí consumidos sin una buena razón.
  2. No en realidad podría limpiar los recursos en el finalizador de todos modos
+0

Como puede ver en mis comentarios, la respuesta no está jugando ningún papel aquí. estoy completamente ignorado. –

+6

@Or A: Ya sea que le importe la respuesta o no, todavía está llamando a 'GetResponse', lo que significa que el objeto devuelto todavía debe eliminarse. (Y el patrón recomendado para hacer eso normalmente sería un bloque 'using'.) – LukeH

7

El primero es mejor.

La diferencia es que la instrucción using llamará a deshacerse del objeto envuelto en él. Deshará correctamente de los recursos retenidos.

De MSDN, la instrucción using:

Proporciona una sintaxis conveniente que asegura el correcto uso de los objetos IDisposable.

+0

¿Por qué el voto a favor? – Oded

+0

No tengo idea, así que subí para compensar. –

+0

Probablemente fue de alguien que todavía piensa que llamar a 'Dispose' es opcional. Aquí hay un +1 para compensar ... aunque Steven ya lo hizo. –

4

Soy consciente de que usted no está interesado en la respuesta. Sin embargo, el objeto de respuesta se ha creado, inicializado y devuelto a su código, lo haya querido o no. Si no lo eliminas, se quedará consumiendo recursos hasta que el GC eventualmente llegue a finalizarlo.

2

estoy de acuerdo con lo que han dicho otros, pero si usted tiene tal odio por el uso de la sintaxis(), se puede hacer:

((IDisposable)request.GetResponse()).Dispose(); 
return true; 
+1

Sí, está bien, aunque' using' es mejor en casi todos los demás casos. –

+0

Y la razón por la que 'using' es mejor, es que asegura que se llama a Dispose incluso si se produce una excepción. – AaronLS

+0

El uso es mejor si puede producirse una excepción entre el momento en que se crea el objeto y el momento en que se elimina. La única manera que podría ocurrir en el código anterior sería si GetResponse de alguna manera devolviera algo que no sea un iDisposable, en cuyo caso el uso no ayudaría de ninguna manera. – supercat

1

La GC no se preocupa por nada que no sea la memoria, por lo que si Tengo mucha memoria y no la consumo en gran medida, podría pasar mucho tiempo hasta que aparezca un GC. Durante todo ese tiempo, los recursos no administrados, como las conexiones de red, los identificadores de archivo, las conexiones de bases de datos, los identificadores de gráficos, etc., permanecen atados por los objetos que están esperando ser GC. Esto puede hacer que se quede sin estos recursos y el GC no tendrá en cuenta porque no supervisa los recursos no administrados.

Así que si coloca el código en un bucle y sigue llamándolo, sin llamar a Dispose, puede encontrar que se degrada rápidamente en el rendimiento (procesos que luchan por recursos escasos) o le da una excepción debido a la falta de recursos no administrados . Depende del contexto de cómo se llama y cómo está creando otros objetos relacionados. En lugar de analizar cada situación, siempre es más seguro llamar a Dispose tan pronto como haya terminado con la instancia.

Es cierto que el GC desistirá con el tiempo de un objeto que se haya salido del alcance/ya no se haga referencia a él, pero esto es indeterminista. Al ser indeterminista, puede ver resultados diferentes en cuanto a la disponibilidad de los recursos al realizar pruebas frente a producción y generar excepciones aleatorias por no asignar recursos cuando se agoten. Si pudieras elegir entre el comportamiento determinista consistente de tu aplicación y la indeterminística, probablemente querrías algo determinista, a menos que tal vez estés tratando de confundir a tus probadores.

Cuestiones relacionadas