c# - tipo - Recolector de basura y referencia circular
referencia circular c# (4)
El recolector de basura .Net puede manejar absolutamente referencias circulares. La vista de muy alto nivel de cómo funciona el recolector de basura es ...
- Comience con locales, estática y objetos fijados GC. Ninguno de estos puede ser recolectado
- Marque cada objeto que se puede alcanzar al atravesar a los niños de estos objetos
- Recoge todos los objetos que no estén marcados.
Esto permite que las referencias circulares se recopilen muy bien. Siempre que ninguno de ellos sea accesible desde un objeto que se sabe que no se puede recoger, entonces la referencia circular es esencialmente irrelevante.
Nota: me doy cuenta de que he omitido muchos detalles divertidos para mantener esta respuesta simple y directa
Considera estas dos clases:
public class A
{
B b;
public A(B b) { this.b = b; }
}
public class B
{
A a;
public B() { this.a = new A(this); }
}
Si tengo clases diseñadas como las anteriores, ¿Garbage Collector (GC) recogería los objetos de dichas clases?
Supongamos que hago esto:
void f()
{
B b = new B();
}
En este método, creo una instancia de B
llamada b
, y cuando el método retorna, b
sale del alcance, y el GC debería ser capaz de recopilarlo, pero si fuera a recopilarlo, tendría que recopilar a
primera que es el miembro de B
, y para recolectar a
, primero tiene que juntar b
que es el miembro de A
Se vuelve circular. Entonces mi pregunta es: ¿tal referencia circular va a evitar que GC recolecte los objetos?
- Si es así, ¿cómo podemos evitar este problema? ¿Cómo podemos asegurarnos de que no tengamos referencias circulares en nuestro diseño de clase? ¿Hay alguna herramienta (o opción de compilación) que nos ayude a detectar referencias circulares?
- Si no, ¿dónde y por qué usamos la clase
WeakReference
? ¿Cual es su propósito?
No, esa referencia circular no afectará al recolector de basura, y será perfectamente capaz de recolectar la instancia de B.
El recolector de basura sabe que nadie puede hacer referencia a la instancia de B después de salir del alcance, y en consecuencia, nadie puede usar la instancia de B para hacer referencia indirecta a A.
No, esto no será un problema porque GC puede manejar referencias circulares
MSDN dice
Si un grupo de objetos contiene referencias el uno al otro, pero ninguno de estos objetos se referencia directa o indirectamente desde la pila o las variables compartidas, la recolección de basura recuperará automáticamente la memoria.
Varias respuestas ya explicaron que las referencias circulares no son un problema.
En cuanto a las referencias débiles, la razón para usarlas es el almacenamiento en caché.
Cuando GC recorre árboles de dependencia de objetos, ignora las referencias débiles. En otras palabras, si la única referencia a un objeto es débil (s), será basura recolectada, pero si no hubo recolección de basura entre la creación de referencia y su intento de usar, aún puede acceder al objeto.