Establecer objetos a Null / Nada después de su uso in.NET


Debe establecer todos los objetos a null (Nothing en VB.NET) una vez que haya terminado con ellos?

Entiendo que en. NET es esencial disponer de cualquier instancia de objetos que implementen la interfaz IDisposable para liberar algunos recursos, aunque el objeto todavía puede ser algo después de que se disponga (de ahí la propiedad isDisposed en formularios), por lo que asumo que todavía puede residir en memoria o al menos en parte?

También sé que cuando un objeto sale del alcance se marca para la recolección listo para el siguiente paso del recolector de basura (aunque esto puede tomar tiempo).

Así que con esto en mente se configurará a null acelerar el sistema de liberación de la memoria, ya que no tiene que funcionar que ya no está en el alcance y son ellos efectos secundarios malos?

Los artículos de MSDN nunca hacen esto en ejemplos y actualmente lo hago porque no puedo ver el daño. Sin embargo, me he encontrado con una mezcla de opiniones, por lo que cualquier comentario es útil.

Author: mattytommo, 2008-08-06

13 answers

Karl es absolutamente correcto, no hay necesidad de establecer objetos en null después de su uso. Si un objeto implementa IDisposable, solo asegúrese de llamar a IDisposable.Dispose() cuando haya terminado con ese objeto (envuelto en un try..finally, o, un bloque using()). Pero incluso si no recuerda llamar a Dispose(), el método finaliser en el objeto debería llamar a Dispose() por usted.

Pensé que este era un buen trato:

Excavar en IDesposable

Y esto

Comprensión Identificable

No tiene sentido tratar de adivinar el GC y sus estrategias de gestión porque es autoajustable y opaco. Hubo una buena discusión sobre el funcionamiento interno con Jeffrey Richter en Dot Net Rocks aquí: Jeffrey Richter en el Modelo de Memoria de Windows y Richters book CLR vía C # el capítulo 20 tiene un gran tratamiento:

 67
Author: Kev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-01-27 12:22:32

Otra razón para evitar establecer objetos en null cuando haya terminado con ellos es que en realidad puede mantenerlos vivos por más tiempo.

Por ejemplo

void foo()
{
    var someType = new SomeType();
    someType.DoSomething();
    // someType is now eligible for garbage collection         

    // ... rest of method not using 'someType' ...
}

Permitirá que el objeto referido por SomeType sea GC'd después de la llamada a "doSomething" pero

void foo()
{
    var someType = new SomeType();
    someType.DoSomething();
    // someType is NOT eligible for garbage collection yet
    // because that variable is used at the end of the method         

    // ... rest of method not using 'someType' ...
    someType = null;
}

A veces puede mantener el objeto vivo hasta el final del método. El JIT normalmente optimizará la asignación a null, por lo que ambos bits de código terminan siendo los mismos.

 34
Author: Wilka,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-08-15 14:43:34

No no hay objetos nulos. Usted puede comprobar hacia fuera http://codebetter.com/blogs/karlseguin/archive/2008/04/27/foundations-of-programming-pt-7-back-to-basics-memory.aspx para obtener más información, pero establecer las cosas en null no hará nada, excepto ensuciar su código.

 15
Author: Karl Seguin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-08-05 20:28:55

También:

using(SomeObject object = new SomeObject()) 
{
  // do stuff with the object
}
// the object will be disposed of
 7
Author: Steve Tranby,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-08-05 20:37:30

En general, no hay necesidad de anular objetos después de su uso, pero en algunos casos me parece una buena práctica.

Si un objeto implementa IDisposable y se almacena en un campo, creo que es bueno anularlo, solo para evitar usar el objeto dispuesto. Los errores del siguiente tipo pueden ser dolorosos:

this.myField.Dispose();
// ... at some later time
this.myField.DoSomething();

Es bueno anular el campo después de desecharlo, y obtener un NullPtrEx justo en la línea donde se usa de nuevo el campo. De lo contrario, podría encontrarse con algún error críptico en la línea (dependiendo de lo que Haceralgo hace).

 7
Author: dbkk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-08-09 11:16:04

Es probable que su código no esté suficientemente estructurado si siente la necesidad de null variables.

Hay varias maneras de limitar el alcance de una variable:

Como lo menciona Steve Tranby

using(SomeObject object = new SomeObject()) 
{
  // do stuff with the object
}
// the object will be disposed of

Del mismo modo, simplemente puede usar corchetes rizados:

{
    // Declare the variable and use it
    SomeObject object = new SomeObject()
}
// The variable is no longer available

Me parece que el uso de corchetes sin ningún "encabezado" para limpiar realmente el código y ayudar a que sea más comprensible.

 6
Author: mbillard,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-08-09 12:13:12

La única vez que debe establecer una variable en null es cuando la variable no sale de su ámbito y ya no necesita los datos asociados con ella. De lo contrario no hay necesidad.

 5
Author: Bob,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-08-05 20:32:48

En general no hay necesidad de establecer null. Pero supongamos que tiene una funcionalidad de reinicio en su clase.

Entonces podría hacerlo, porque no desea llamar a dispose dos veces, ya que algunos de los Dispose pueden no implementarse correctamente y el Sistema throw.ObjectDisposed exception.

private void Reset()
{
    if(_dataset != null)
    {
       _dataset.Dispose();
       _dataset = null;
    }
    //..More such member variables like oracle connection etc. _oraConnection
 }
 5
Author: Munish Goyal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-04-17 08:55:49

Este tipo de "no hay necesidad de establecer objetos en null después de su uso" no es del todo exacto. Hay veces que necesita ANULAR la variable después de desecharla.

Sí, siempre debes llamar a .Dispose() o .Close() en cualquier cosa que lo tenga cuando hayas terminado. Ya sean manejadores de archivos, conexiones de bases de datos u objetos desechables.

Aparte de eso está el patrón muy práctico de LazyLoad.

Digamos que he instanciado ObjA de class A. Class A tiene una propiedad pública llamada PropB de class B.

Internamente, PropB usa la variable privada de _B y el valor predeterminado es null. Cuando se usa PropB.Get(), comprueba si _PropB es null y si lo es, abre los recursos necesarios para instanciar un B en _PropB. Luego devuelve _PropB.

Para mi experiencia, este es un truco muy útil.

Donde entra la necesidad de null es si restablece o cambia A de alguna manera que el contenido de _PropB era el hijo de los valores anteriores de A, necesita Disponer Y anular _PropB para que LazyLoad pueda restablecerse para obtener el valor correcto SI el código lo requiere.

Si solo haces _PropB.Dispose() y poco después esperas que la comprobación null para LazyLoad tenga éxito, no será null, y estarás viendo datos obsoletos. En efecto, debe anularlo después de Dispose() solo para estar seguro.

Ojalá fuera de otra manera, pero ahora mismo tengo código mostrando este comportamiento después de un Dispose() en un _PropB y fuera de la función de llamada que hizo el Dispose (y por lo tanto casi fuera de alcance), el prop privado todavía no es nulo, y los datos obsoletos todavía están allí.

Eventualmente, la propiedad eliminada se anulará, pero eso no ha sido determinista desde mi perspectiva.

La razón principal, como alude dbkk, es que el contenedor padre (ObjA con PropB) mantiene la instancia de _PropB en el alcance, a pesar de la Dispose().

 3
Author: KenF,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-06-09 16:56:16

Hay algunos casos en los que tiene sentido hacer referencias nulas. Por ejemplo, cuando estás escribiendo una colección, como una cola de prioridad, y por tu contrato, no deberías mantener esos objetos vivos para el cliente después de que el cliente los haya eliminado de la cola.

Pero este tipo de cosas solo importa en colecciones de larga vida. Si la cola no va a sobrevivir al final de la función en la que fue creada, entonces importa mucho menos.

En general, realmente no debería molestarme. Deje que el compilador y GC hagan su trabajo para que usted pueda hacer el suyo.

 1
Author: Patrick,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-08-05 20:46:08

Echa un vistazo a este artículo también: http://www.codeproject.com/KB/cs/idisposable.aspx

En su mayor parte, establecer un objeto a null no tiene ningún efecto. La única vez que debe asegurarse de hacerlo es si está trabajando con un "objeto grande", que es uno más grande que 84K en tamaño (como mapas de bits).

 1
Author: Scott Dorman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-11-01 03:47:17

Creo que por diseño de los implementadores de GC, no se puede acelerar GC con anulación. Estoy seguro de que preferirían que no te preocupes por cómo / cuándo se ejecuta GC treat trátalo como este ubicuo Siendo protegiéndote y velando por ti...(inclina la cabeza hacia abajo, levanta el puño al cielo)...

Personalmente, a menudo establezco explícitamente variables en null cuando he terminado con ellas como una forma de auto documentación. No declaro, uso, luego establezco a null más tarde I I null inmediatamente después de que ya no sean necesarios. Estoy diciendo, explícitamente, " Oficialmente he terminado con you...be se fue..."

¿Es necesario anular en un lenguaje GC'd? No. ¿Es útil para el GC? Tal vez sí, tal vez no, no lo sé con certeza, por diseño realmente no puedo controlarlo, e independientemente de la respuesta de hoy con esta versión o esa, futuras implementaciones de GC podrían cambiar la respuesta más allá de mi control. Además si / cuando nulling está optimizado, es poco más que un comentario elegante si lo harás.

Me imagino que si hace que mi intención sea más clara para el próximo pobre tonto que siga mis pasos, y si "podría" potencialmente ayudar a GC a veces, entonces vale la pena para mí. Sobre todo me hace sentir ordenado y claro, y a Mongo le gusta sentirse ordenado y claro. :)

Lo veo así: Los lenguajes de programación existen para permitir que las personas le den a otras personas una idea de intención y un compilador una solicitud de trabajo de qué hacer the el compilador convierte esa solicitud en una solicitud diferente idioma (a veces varios) para una CPU the la(s) CPU (s) podría (n) dar un toque a qué idioma utilizaste, tus ajustes de pestañas, comentarios, énfasis estilístico, nombres de variables, etc. -- una CPU tiene que ver con el flujo de bits que le dice qué registros y opcodes y ubicaciones de memoria para girar. Muchas cosas escritas en código no se convierten en lo que consume la CPU en la secuencia que especificamos. Nuestro C, C++, C#, Lisp, Babel, ensamblador o lo que sea es teoría más que realidad, escrito como una declaración de trabajo. Lo que ves no es lo que obtienes, sí, incluso en lenguaje ensamblador.

Entiendo la mentalidad de "cosas innecesarias" (como líneas en blanco) "no son más que ruido y desorden de código."Ese era yo al principio de mi carrera; lo entiendo totalmente. En esta coyuntura me inclino hacia lo que hace que el código sea más claro. No es como si estuviera agregando incluso 50 líneas de "ruido" a mis programas's son unas pocas líneas aquí o allá.

Hay excepciones a cualquier regla. En escenarios con memoria volátil, estática memoria, condiciones de carrera, singletons, uso de datos "rancios" y todo ese tipo de putrefacción, eso es diferente: necesitas administrar tu propia memoria, bloqueándola y anulándola a propósito porque la memoria no es parte del Universo GC'd hopefully esperemos que todo el mundo entienda eso. El resto del tiempo con los lenguajes GC'd es una cuestión de estilo en lugar de necesidad o un aumento de rendimiento garantizado.

Al final del día, asegúrese de comprender qué es elegible para GC y qué no; bloquee, deseche, y anular apropiadamente; encerar, encerar; inhalar, exhalar; y para todo lo demás digo: Si se siente bien, hazlo. Su kilometraje puede vary...as debería...

 0
Author: John,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-05-10 13:07:53

Algún objeto supone el método .dispose() que obliga a eliminar el recurso de la memoria.

 -1
Author: GateKiller,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-08-07 20:52:26