1.Si tengo algo así como Foo o = new Foo(); dentro del método, ¿significa que significa que cada vez que el temporizador marca, estoy creando un nuevo objeto y una nueva referencia a ese objeto?
Sí.
2. Si he cadena foo = null y luego sólo hay que poner algo temporal en foo, es el mismo que el anterior?
Si está preguntando si el comportamiento es el mismo, entonces sí.
3.Does el recolector de basura cada vez eliminar el objeto y la referencia o objetos se crean continuamente y estancia en la memoria?
La memoria utilizada por esos objetos se recoge con toda seguridad después de que las referencias se consideren no utilizadas.
4.Si declaro Foo o; y no apuntarlo a ninguna instancia, ¿no es eso eliminado cuando finaliza el método?
No, ya que no se ha creado ningún objeto, entonces no hay objeto para recopilar (no es la palabra correcta).
5.Si quiero asegurar que todo se borra, lo que es la mejor manera de hacerlo
Si la clase del objeto implementa IDisposable
entonces ciertamente desea llamar con avidez Dispose
tan pronto como sea posible. La palabra clave using
lo hace más fácil porque llama al Dispose
automáticamente de forma segura.
Aparte de eso, no hay nada más que deba hacer, excepto dejar de usar el objeto. Si la referencia es una variable local, cuando se sale del alcance será elegible para la recopilación. Si se trata de una variable de nivel de clase, es posible que deba asignarle null
para que sea elegible antes de que la clase que lo contiene sea elegible.
Esto es técnicamente incorrecto (o al menos un poco engañoso). Un objeto puede ser elegible para la recopilación mucho antes de que salga del alcance. El CLR está optimizado para recolectar memoria cuando detecta que una referencia ya no se usa. En casos extremos, el CLR puede recolectar un objeto incluso cuando uno de sus métodos aún se está ejecutando.
Actualización:
Aquí es un ejemplo que demuestra que la GC se recogen objetos a pesar de que todavía pueden estar en el estudio. Debe compilar una compilación de versión y ejecutar esto fuera del depurador.
static void Main(string[] args)
{
Console.WriteLine("Before allocation");
var bo = new BigObject();
Console.WriteLine("After allocation");
bo.SomeMethod();
Console.ReadLine();
// The object is technically in-scope here which means it must still be rooted.
}
private class BigObject
{
private byte[] LotsOfMemory = new byte[Int32.MaxValue/4];
public BigObject()
{
Console.WriteLine("BigObject()");
}
~BigObject()
{
Console.WriteLine("~BigObject()");
}
public void SomeMethod()
{
Console.WriteLine("Begin SomeMethod");
GC.Collect();
GC.WaitForPendingFinalizers();
Console.WriteLine("End SomeMethod");
}
}
En mi máquina del finalizador se ejecuta mientras se sigue ejecutando SomeMethod
!
¿cómo exactamente terminarías dentro del método de un objeto sin que ese objeto tenga una referencia rooteada? – Yaur
@Yaur: Buena pregunta: Considere un método de instancia que no use otros miembros de instancia (variables o métodos). Eso significa que la referencia del objeto solo necesita extraerse para pasar la referencia 'this'. Después de eso, el objeto es técnicamente elegible siempre que el CLR pueda detectar que no se usa más adelante aunque todavía esté rooteado. –
@Brian Gideon Veo su punto, pero soy escéptico ya que el CLR utiliza la marca y el barrido para determinar si el GC es elegible para que esto suceda o que el objeto es incluso técnicamente "elegible" para la recolección de basura.Pero esto es, en cualquier caso, un caso bastante interesante para hacer algunas pruebas. – Yaur