tôi có mã này:Resurrection sự khác biệt trong việc sử dụng Object Initializer
Về cơ bản tôi đang cố gắng để chứng minh việc sử dụng C# finalizer và làm cho một đối tượng mà không thể chết, tôi gọi nó là Zombie. Bây giờ, bình thường bản demo này hoạt động rất tốt, nhưng hôm nay tôi đã thử sử dụng cùng một mã với bộ khởi tạo đối tượng thay vì chỉ gán cho thuộc tính (Tên trong trường hợp này). Tôi nhận thấy có sự khác biệt. Cụ thể là các finalizer không bao giờ được gọi là, ngay cả khi tôi đang cố gắng hết sức để làm cho Garbage Collector làm việc đó.
Ai đó có thể giải thích sự khác biệt hay tôi đã tìm thấy lỗi trong trình biên dịch C#?
(Tôi đang sử dụng C# 4 trong VS2010 SP1 trên Win7x64)
Cảm ơn.
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);
}
}
}
}
Khi tôi tạo Zombie z trong một phương thức bổ sung, thì vấn đề thực sự biến mất. tĩnh công cộng Zombie CreateZombie() { trả về Zombie mới {Name = "Guy"}; } – jeroentrappers
Đã thử điều này với VS2012 và .NET 4.5. Tôi không thể tìm thấy bất kỳ trường hợp nào có sự khác biệt giữa trình khởi tạo đối tượng và mã thuộc tính create-first-then-set-property "kiểu cũ". Nếu bạn làm điều này trong chế độ Debug mà không tối ưu hóa, 'GC' sẽ không thu thập' z' (đó là đối tượng 'z' ban đầu được tham chiếu) trước khi phương thức kết thúc. Đó là để gỡ lỗi dễ dàng hơn; nó sẽ không thu thập cho đến khi biến cục bộ nằm ngoài phạm vi một cách chính thức ('z' vẫn nằm trong phạm vi gần cuối phương thức).Nếu bạn trích xuất phần đầu tiên của 'Main' (với' z') ra thành một phương thức riêng biệt, nó cũng sẽ làm việc dưới dạng xây dựng Debug. –