tengo este código:diferencia resurrección en el uso de inicializador de objeto
Esencialmente estoy tratando de demostrar el uso de la C# finalizador y crea un objeto que no puede morir, llamó zombi. Ahora, normalmente esta demostración funciona muy bien, pero hoy traté de usar el mismo código con el inicializador de objetos en lugar de simplemente asignar a la propiedad (Nombre en este caso). Noté que hay una diferencia. A saber, el finalizador nunca se llama, ni siquiera cuando hago mi mejor esfuerzo para que el recolector de basura haga su trabajo.
¿Alguien podría explicar la diferencia, o he encontrado un error en el compilador de C#?
(estoy usando C# 4 en el SP1 de VS2010 en Win7x64)
Gracias.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace Zombie
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Main thread: " + Thread.CurrentThread.ManagedThreadId);
// case 1: this is where the problem is located.
Zombie z = new Zombie { Name = "Guy" }; // object initializer syntax makes that the finalizer is not called.
// case 2: this is not causing a problem. The finalizer gets called.
//Zombie z = new Zombie();
//z.Name = "Guy";
WeakReference weakZombieGuyRef = new WeakReference(z, true);
z = null;
GC.GetTotalMemory(forceFullCollection: true);
GC.Collect();
while (true)
{
Console.ReadKey();
if (weakZombieGuyRef.IsAlive)
{
Console.WriteLine("zombie guy still alive");
}
else
{
Console.WriteLine("Zombie guy died.. silver bullet anyone?");
}
Zombie.Instance = null;
GC.AddMemoryPressure(12400000);
GC.GetTotalMemory(forceFullCollection: true);
GC.Collect();
}
}
}
public class Zombie
{
public string Name { get; set; }
public static Zombie Instance = null;
~Zombie()
{
Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
Console.WriteLine("Finalizer called on zombie" + this.Name);
lock (typeof(Zombie))
{
Instance = this;
GC.ReRegisterForFinalize(this);
}
}
}
}
Cuando creo el Zombie z en un método adicional, entonces el problema desaparece. public static Zombie CreateZombie() { return new Zombie {Name = "Guy"}; } – jeroentrappers
Intenté esto con VS2012 y .NET 4.5. No pude encontrar ningún caso donde haya una diferencia entre el inicializador de objetos y el código "antiguo" de creación-primer-luego-conjunto-propiedad. Si haces esto en el modo de depuración sin optimizaciones, el 'GC' no recogerá' z' (que es el objeto 'z' referenciado originalmente) antes de que el método haya terminado. Eso es para una depuración más fácil; no se recogerá hasta que la variable local esté fuera del alcance de una manera formal ('z' todavía está en el alcance cerca del final del método).Si extraes la primera parte de 'Main' (con' z') en un método separado, funcionará también en Debug build. –