Điều bạn đang thiếu ở đây là trình biên dịch đang kéo dài tuổi thọ của bạn x
biến cho đến khi kết thúc phương thức được định nghĩa - đó chỉ là thứ mà trình biên dịch thực hiện - nhưng nó chỉ thực hiện cho bản dựng DEBUG.
Nếu bạn thay đổi mã để biến được xác định trong một phương thức riêng biệt, nó sẽ hoạt động như bạn mong đợi.
Đầu ra của đoạn mã sau là:
False
True
Và mã:
using System;
namespace ConsoleApp1
{
class Finalizable
{
~Finalizable()
{
_extendMyLifetime = this;
}
public static bool LifetimeExtended => _extendMyLifetime != null;
static Finalizable _extendMyLifetime;
}
class Program
{
public static void Main()
{
test();
Console.WriteLine(Finalizable.LifetimeExtended); // False.
GC.Collect();
GC.WaitForPendingFinalizers();
Console.WriteLine(Finalizable.LifetimeExtended); // True.
}
static void test()
{
new Finalizable();
}
}
}
Vì vậy, về cơ bản sự hiểu biết của bạn là chính xác, nhưng bạn không biết rằng trình biên dịch lén lút sẽ giữ cho biến của bạn tồn tại cho đến khi bạn gọiGC.Collect()
- ngay cả khi bạn đặt nó thành null!
Như tôi đã lưu ý ở trên, điều này chỉ xảy ra đối với bản dựng DEBUG - có lẽ là do đó bạn có thể kiểm tra các giá trị cho các biến cục bộ trong khi gỡ lỗi đến cuối phương thức (nhưng đó chỉ là dự đoán!).
Mã ban đầu DOES hoạt động như mong đợi đối với bản dựng phát hành - do đó, đoạn mã sau xuất ra false, true
cho bản dựng ĐÁNG TIN CẬY và false, false
cho bản dựng DEBUG:
using System;
namespace ConsoleApp1
{
class Finalizable
{
~Finalizable()
{
_extendMyLifetime = this;
}
public static bool LifetimeExtended => _extendMyLifetime != null;
static Finalizable _extendMyLifetime;
}
class Program
{
public static void Main()
{
new Finalizable();
Console.WriteLine(Finalizable.LifetimeExtended); // False.
GC.Collect();
GC.WaitForPendingFinalizers();
Console.WriteLine(Finalizable.LifetimeExtended); // True iff RELEASE build.
}
}
}
Là một phụ lục: Lưu ý rằng nếu bạn làm một cái gì đó trong bộ hoàn thiện cho một lớp làm cho một tham chiếu đến đối tượng được hoàn thành có thể truy cập được từ một gốc chương trình, thì đối tượng đó sẽ KHÔNG được thu gom rác trừ khi và cho đến khi đối tượng đó không còn tham khảo.
Nói cách khác, bạn có thể cho đối tượng "ở lại thực thi" thông qua bộ hoàn thiện. Điều này thường được coi là một thiết kế xấu, mặc dù!
Ví dụ, trong đoạn mã trên, nơi chúng tôi thực hiện _extendMyLifetime = this
trong trình hoàn thiện, chúng tôi đang tạo một tham chiếu mới cho đối tượng, vì vậy bây giờ nó sẽ không được thu gom rác cho đến khi _extendMyLifetime
(và bất kỳ tham chiếu nào khác) không còn tham chiếu đến nó nữa.
Person1
gì? Tôi chỉ nhìn thấyPerson
. Lần cuối: xem docs.microsoft.com/dotnet/csharp/programming-guide/iêu để biết cách thức hoạt động của công cụ hoàn thiện.