2010-05-14 5 views
9

¿Debo llamar a .Dispose() después de devolver un objeto que implementa IDisposable?¿Debo llamar a Dispose() dentro de una función después de Return?

myDisposableObject Gimme() { 
    //Code 
    return disposableResult; 
    disposableResult.Dispose(); 
} 

En otras palabras, ¿el objeto devuelve una copia, o es el objeto en sí? Gracias :)

+0

Consejo: No es responsabilidad del método deshacerse del objeto devuelto. Es el trabajo de quien llama. * Es * la responsabilidad del método para disponer de los recursos que creó, si es necesario. – AMissico

+0

@AMissico: "No es responsabilidad del método deshacerse del objeto devuelto". Desafortunadamente, eso no es cierto en general. Para algunos métodos y algunos captadores de propiedades, la persona que llama es responsable de eliminar el objeto devuelto, para otros no, porque el objeto se almacena en caché en algún lugar y se desecha en otro lugar. Aparentemente, no hay una regla simple para descubrir, excepto prueba y error. – Niki

+2

Además, y si alguien me corrige si me equivoco, su última línea nunca se llama de todos modos ya que la devolución sale del método. –

Respuesta

7

Es el objeto en sí. No llame a Dispose aquí, incluso si invierte el orden para que se llame.

+1

Gracias, respuesta concisa. –

3

El .Dispose() nunca será alcanzado de todos modos.

Editar: En mi opinión, no, no debería. Destruirías el Objeto con eso.

3

Si un objeto está utilizando implementos IDisposable, debe construir y utilizar en el plazo de un comunicado using - esto hará que asegurarse de que se eliminarse de manera adecuada:

using(var mydisposableObject = new Gimme()) 
{ 
    // code 
} 

La manera en que su código está construido, que son devolviendo el objeto desechable, por lo que nunca se alcanzará la llamada al Dispose.

+0

Quise decir esto dentro del cuerpo de la función, no afuera. –

+0

@Camilo Martin: no tiene sentido hacerlo ya que nunca se alcanzará la llamada a 'Dispose'. Debe envolver la llamada a esta función con una instrucción 'using' para que' Dispose' se invoque correctamente cuando el objeto se salga del alcance. – Oded

+0

Si un "return mydisposableObject;" se ejecuta dentro de la instrucción "using", se produce un .Dispositivo de mydisposableObject entre la ejecución de la instrucción return y la primera oportunidad de que la persona que llama utilice mydisposableObject.En la mayoría de los casos, esto hará que mydisposableObject sea completamente inútil para la persona que llama. – supercat

4

desechableResult.Dispose(); nunca se ejecutará, es un código inalcanzable ya que siempre devolverá la línea anterior. Envuelva la llamada al método en un stamement de uso y deshágase del objeto de esa manera.
p.

using (DisposeableObject myDisposableObject = gimme()) 
{ 
    //code. 
} 
+0

Su código dará lugar a error de compilación, porque usó la palabra clave 'objeto' para nombrar una variable: P – prostynick

+2

Sí, también, no creo que el" ... código ". la sección es una sintaxis válida ;-) La cambié de todos modos. –

+0

@prostynick: Es solo un código de ejemplo, no hay necesidad de objetar. – AMissico

9

No, no deberías. Usted devuelve una referencia al objeto, por lo que no se realiza ninguna copia. En .NET los objetos nunca se copian a menos que específicamente lo solicite.

Además, no puede deshacerse del objeto con un código como ese, incluso si hubiera una situación en la que debería. El código después de la declaración return nunca se ejecutará, y recibirá una advertencia sobre el código inalcanzable.

1

Esta línea: disposableResult.Dispose(); no se ejecutará. La "cosa" devuelta no es una copia del objeto. Es una referencia al objeto, por lo que la persona que llama manipulará el objeto creado en Gimme y él (el que llama) debe recordar desechar el objeto.

1

Se puede envolver su código en un try/finally

try{ 
      int a = 0; 
      return; 
    } 
    finally{ 
      //Code here will be called after you return 
    } 
2

Si devuelve el objeto, que debe no deshacerse de él antes de su regreso. Tiene que ser decisión de la persona que llama disponer de él.

0

myDisposableObject disposableResult = new myDisposableObject();

Aquí disposableResult es una referencia al nuevo objeto creado. Entonces, cuando devuelve esa referencia al método de llamada, esa referencia aún apunta al objeto creado en el montón. Por lo tanto, puede disponer de forma segura en el método de llamada.

0

No puede tener .Dispose() en el método que se devuelve. La persona que llama debe implementar eso.

7

Una cosa que ninguna de las respuestas hasta ahora ha mencionado es que usted debería disponer del objeto si Gimme arroja una excepción.Por ejemplo:

MyDisposableObject Gimme() 
{ 
    MyDisposableObject disposableResult = null; 
    try 
    { 
     MyDisposableObject disposableResult = ... 

     // ... Code to prepare disposableResult 

     return disposableResult; 
    } 
    catch(Exception) 
    { 
     if (disposableResult != null) disposableResult.Dispose(); 
     throw; 
    } 
} 
+0

+1, Interesante, no lo sabía. Empezaré a hacer eso con objetos propensos a excepciones. –

+0

Esta es una buena sugerencia en general para fábricas, etc. - pero con el código que publicó, no estoy tan seguro - y tal vez solo sea un pseudo código - pero en el código que publicó, no lo hizo 't * create * desechableResult - podría ser un objeto compartido, etc. - el dueño de un objeto debería ser el que lo desechará ... si creó el objeto (o causó la creación del objeto) y simplemente iba a configurarlo y devolverlo, pero arrojó una excepción en el proceso, entonces sí, debería ser el que lo elimine en este escenario. – BrainSlugs83

1

estoy de acuerdo no deseche este objeto que se pasa por referencia .. Hay un caso particular que se me ocurre cuando el desove objetos donde una clase envuelve otra clase y dispensa objetos: no lo hace quiere que el objeto dispensado sea una referencia al mismo para clonar o pasar una copia del objeto y destruir el original; sin embargo, si el original es una imagen estándar para todos los engendros de ese tipo, el objeto no se crea específicamente para cada llame y anticipa que doceus genera en un corto período de tiempo, puede conservarlo ya que puede generar un nuevo objeto a partir de esa imagen sin tener que volver a crear una instancia de nuevo. Seleccionaría bloquear todas las propiedades en este para que sea de solo lectura y emitir el Objeto de solo lectura para un objeto de lectura/escritura que se puede usar en el mundo real. El objeto no debe ejecutar ningún subproceso dentro de sí mismo cuando se pasa como copia de valor o clonar, sin embargo, si está enhebrando, está perfectamente bien pasar su referencia siempre que la referencia sea una relación 1 a 1, si tiene múltiples punteros. a un objeto que simultáneamente esté leyendo y escribiendo en ese objeto "imagen en ejecución" puede comenzar a tener colisiones donde un valor no se ha almacenado de manera segura y el siguiente pinger solicita y asigna ese mismo valor. Una cosa que no discutimos cuando estaba en la escuela en gran medida es el estado de los objetos. Los principios orientados a objetos estaban arraigados, pero entender por qué se establecieron siempre ha llevado tiempo. Soy backwords. Aprendí estilo orientado a objetos y luego me mudé a más estilos de procedimiento.

+0

¡Bienvenido a SO! Esta pregunta mía es de hace 2.5 años, así que solo puedo comentar sobre el estilo de escritura de tu respuesta: por favor, considera mejorarla un poco, ya que en su estado actual se parece un poco a un muro de texto. También tiene algunos errores tipográficos, y la gente aquí tiende a ser sensible a eso. Dicho esto, gracias de nuevo por pasar y responder. –

+0

Lo siento por el muro de texto, solo quería indicar una instancia en la que destruiríamos un objeto. –

Cuestiones relacionadas