Tôi có một lớp học giữ một đại biểu, để đánh giá một cách lười biếng một cái gì đó sau này.GC của các đại biểu, tôi đang thiếu gì? (đại biểu của tôi không được thu thập)
Khi tôi đã đánh giá nó, bằng cách gọi cho đại biểu, tôi xóa tài liệu tham khảo cho đại biểu, hy vọng rằng nó sẽ đủ điều kiện để thu thập. Sau khi tất cả, nó có thể giữ cho một thế giới của các biến địa phương nếu nó được xây dựng như một phương pháp vô danh.
Tôi đã thử xây dựng một đơn vị kiểm tra để xác minh điều này, nhưng dường như không đúng cách tôi lên kế hoạch, thay vào đó có vẻ như giả định của tôi về WeakReference
(mà tôi đã sử dụng cho mục đích thử nghiệm ở đây) giả định khác, không giữ nước.
Hãy nhìn vào mã này, mà bạn có thể chạy trong LINQPad
void Main()
{
WeakReference wr;
Lazy<int> l;
CreateTestData(out wr, out l);
wr.IsAlive.Dump(); // should be alive here
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
wr.IsAlive.Dump(); // and alive here as well
l.Value.Dump(); // but now we clear the reference
GC.Collect(); // so one of these should collect it
GC.WaitForPendingFinalizers();
GC.Collect();
wr.IsAlive.Dump(); // and then it should be gone here
GC.KeepAlive(l);
}
void CreateTestData(out WeakReference wr, out Lazy<int> l)
{
Func<int> f =() => 10;
wr = new WeakReference(f);
l = new Lazy<int>(f);
}
public class Lazy<T>
{
private Func<T> _GetValue;
private T _Value;
public Lazy(Func<T> getValue)
{
_GetValue = getValue;
}
public T Value
{
get
{
if (_GetValue != null)
{
_Value = _GetValue();
_GetValue = null;
}
return _Value;
}
}
}
tôi đã giả định rằng:
- Bất kể build DEBUG, debugger đính kèm, kể từ khi tôi tạo ra các đại biểu trong một phương pháp riêng biệt, mà tôi trở về từ, không có gì giữ cho đại biểu, ngoại trừ
WeakReference
và các đối tượngLazy<T>
- Nếu tôi yêu cầuĐối tượng 210 để từ bỏ tham chiếu của nó với đại biểu, sẽ giảm tham chiếu đến chỉ số mà
WeakReference
đang giữ trên - Sau đó bắt buộc thu thập rác đầy đủ, giả sử rằng tham chiếu duy nhất còn lại là tham chiếu trong
WeakReference
- Sau đó, các đại biểu sẽ được thu thập, và
WeakReference
tôi sẽ chỉ ra rằng đối tượng không còn sống
Đầu ra của mã đã được như vậy, dự kiến sẽ được (với ý kiến):
true // not gc'ed after construction
true // not gc'ed after full GC, still beind held by Lazy<T>
10 // value from calling delegate
false // but is now gc'ed, Lazy<T> no longer has a reference to it
Nhưng thay vì đầu ra là:
true
true
10
true
bất cứ ai có thể làm sáng tỏ về những gì tôi đang thiếu ở đây?
Ok, điều đó có ý nghĩa. Tôi đã thay đổi các đại biểu để nó được sử dụng một biến địa phương để tính toán kết quả của nó thay vào đó, và đó thực sự là thu thập. –
Câu hỏi phụ: Tôi giả định trình biên dịch không đủ thông minh để nhận thấy rằng nhiều đại biểu, cùng loại, trả về cùng một giá trị không đổi, có thể được tạo một lần và sử dụng lại ở mọi nơi? –
Về cơ bản, mục tiêu của tôi là có một bài kiểm tra xác minh rằng tham chiếu đến đại biểu được từ bỏ vào đúng thời điểm, để có thể thu thập rác ở nơi được phép, không nhất thiết là đại biểu cụ thể đó đã được thu thập.Thay đổi đại biểu chỉ giải quyết được chút ít vấn đề đó và các thử nghiệm hiện chạy như mong đợi. –