Pregunta

Tengo algunas clases que contienen referencias a otras clases a través de miembros de instancia IDictionary.

Me gusta así:

class A
{
  private readonly Dictionary<int, B> _particles = new Dictionary<int, B>();
  public void CreateNewB(int someInt)
   {
     var b = new B();
     if (!_particles.ContainsKey(someInt)
         _particles.Add(someInt, b);
   }
}

así que esta es la configuración, y NUNCA los elimino de este diccionario, pero por alguna razón, el destructor para la clase B se llama en un GC que se ejecuta de vez en cuando y no entiendo por qué.

¿Podría tener algo que ver con cómo la clase Diccionario agrega nuevas referencias?

FIJO :

Ok, gracias a todos por sus respuestas, ciertamente tengo una gran comprensión sobre el GC y los deconstructores ahora.

Pero el problema era mío, estaba agregando someInt solo si aún no existía y a través de una lógica comercial defectuosa, someInt siempre era 1, así que la primera vez a través de esto funcionó y los deconstructores no fueron llamados. Pero la segunda vez, sin embargo, la "b" la instancia simplemente no se agregó a la lista y se limpió en la ejecución del GC.

¡Gracias de nuevo a todos los que ayudaron!

¿Fue útil?

Solución 5

Ok, gracias a todos por sus respuestas, ciertamente tengo una gran comprensión sobre el GC y los deconstructores ahora.

Pero el problema era mío, estaba agregando someInt solo si aún no existía y, a través de una lógica comercial defectuosa, someInt siempre fue 1, por lo que la primera vez funcionó y no se llamó a los deconstructores. Pero la segunda vez, sin embargo, la "b" la instancia simplemente no se agregó a la lista y se limpió en la ejecución del GC.

Estoy respondiendo esto solo para cerrarlo :)

Otros consejos

Su clase B será GC si la referencia a la clase A está muerta

  

NUNCA los elimino de esto   diccionario, pero por alguna razón, el   el destructor para la clase B se llama

El destructor en .NET no es lo mismo que el destructor en C ++ (no administrado).
Destructor llama al Finalizar método automáticamente.

Estas son algunas características de un destructor :

  • Los destructores no se pueden definir en estructuras. Solo se usan con clases.
  • Una clase solo puede tener un destructor.
  • Los destructores no se pueden heredar ni sobrecargar.
  • Destructores no se pueden llamar . Se invocan automáticamente .
  • Un destructor no toma modificadores ni tiene parámetros.

Entonces, lo que sucede en su caso es esto (en 2 palabras):

  1. La clase A es basura recolectada.
  2. Como resultado de 1: campo _partículas obtener GC-d.
  3. Como resultado de 2: las entradas en el Diccionario quedaron sin raíz (disponibles para la Recolección de Basura).
  4. Como resultado de 3: las entradas en el Diccionario (instancias de clase B) son GC-d.
  

¿Podría tener algo que ver con cómo   la clase Diccionario agrega nuevo   referencias?

No.

Parece que estás haciendo algo muy mal. En un entorno administrado, mantener una referencia como esta que esencialmente vivirá para siempre equivale a una pérdida de memoria, a menos que realmente quiera mantener estos objetos cerca.

La otra cosa para recordar aquí es que no existe un destructor en C #. Lo que tienes son finalizadores , que son diferentes. Es raro con el código administrado que incluso deba escribir un finalizador. La única buena razón para hacerlo es cuando está implementando IDisposable para un tipo para envolver un recurso no administrado que aún no está cubierto por un finalizador .

Por ejemplo, muchas personas crean un tipo que implementa IDisposable y envuelve SqlConnection como parte de su capa de acceso a datos. De esta forma, pueden envolver instancias del tipo usando bloques y asegurarse de que todas las conexiones SqlConnections que creen estén dispuestas correctamente. Pero este tipo no necesita un finalizador, porque la conexión de la base de datos subyacente ya está cubierta por el finalizador en la clase SqlConnection. No hay que preocuparse por el tipo de recurso no administrado nuevo , solo el tipo SqlConnection. Pero si estaba creando un motor de base de datos completamente nuevo e implementaba el nuevo proveedor de datos .Net para él, desearía implementar un finalizador para su conexión.

Entonces tengo el siguiente tipo:

type k {
public k() { Console.WriteLine("Hi, I'm a new K!"); }
public ~k() { Console.WriteLine("I'm a dying K!"); }
}

Y un pequeño fragmento de código:

Dictionary<int, k> ks = new Dictionary<int, k);
for(int i=0;i<10;i++) { ks.add(i, new k()); }

y ves que ~ k () está siendo llamado en un punto? ¿Eso está pasando?

Apostaría mi dinero a que la clase B se cree en otro lugar. Si se trata de una aplicación de consola, muestre algo en B constructor y finalizador. Asegúrese de que el número de instancias es lo que espera que sea.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top