是否有可能钩住被GC收集的对象?

本文关键字:对象 GC 有可能 是否 | 更新日期: 2023-09-27 18:18:51

假设我有目标强引用的WeakReference。我想知道目标对象本身何时被GC收集。这可能吗?

编辑:此处不允许向终结器/析构函数添加代码。我需要的东西是不依赖于类代码

是否有可能钩住被GC收集的对象?

在。net 4.0和之后使用ConditionalWeakTable<TKey, TValue>是可能的。感谢这个网站和其他网站。它遵循概念验证代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.CompilerServices;
namespace Test
{
    public static class GCInterceptor
    {
        private static ConditionalWeakTable<object, CallbackRef> _table;
        static GCInterceptor()
        {
            _table = new ConditionalWeakTable<object, CallbackRef>();
        }
        public static void RegisterGCEvent(this object obj, Action<int> action)
        {
            CallbackRef callbackRef;
            bool found = _table.TryGetValue(obj, out callbackRef);
            if (found)
            {
                callbackRef.Collected += action;
                return;
            }
            int hashCode = RuntimeHelpers.GetHashCode(obj);
            callbackRef = new CallbackRef(hashCode);
            callbackRef.Collected += action;
            _table.Add(obj, callbackRef);
        }
        public static void DeregisterGCEvent(this object obj, Action<int> action)
        {
            CallbackRef callbackRef;
            bool found = _table.TryGetValue(obj, out callbackRef);
            if (!found)
                throw new Exception("No events registered");
            callbackRef.Collected -= action;
        }
        private class CallbackRef
        {
            private int _hashCode;
            public event Action<int> Collected;
            public CallbackRef(int hashCode)
            {
                _hashCode = hashCode;
            }
            ~CallbackRef()
            {
                Action<int> handle = Collected;
                if (handle != null)
                    handle(_hashCode);
            }
        }
    }
}

用以下代码测试:

public partial class Form1 : Form
{
    private object _obj;
    public Form1()
    {
        InitializeComponent();
        _obj = new object();
        _obj.RegisterGCEvent(delegate(int hashCode)
        {
            MessageBox.Show("Object with hash code " + hashCode + " recently collected");
        });
    }
    private void button1_Click(object sender, EventArgs e)
    {
        _obj = null;
        GC.Collect();
        GC.WaitForPendingFinalizers();
    }
}

Object.Finalize()方法如何?它不会在完成时被调用吗?

您可以使用拦截来捕获从自定义接口/类继承的每个类的Finalize。我想,这就是你想要达到的目标,对吧?你可以使用Unity。以下是一个如何使用Unity进行拦截的简短示例。