自定义WeakReference实现

ubi*_*biq 7 .net c# garbage-collection

BCL中的WeakReference是在仿制药时代设计的,因此它的界面并不尽如人意.IsAlive属性也很容易被误用.查看WeakReference槽Reflector的实现,我们似乎可以自己实现它.这是我想出的:

    [SecurityPermission(Flags = SecurityPermissionFlag.UnmanagedCode)]
    public sealed class WeakRef<T> where T : class
    {
        private readonly volatile IntPtr _ptr;

        public WeakRef(T target)
            : this(target, false)
        {
        }

        [SecuritySafeCritical]
        public WeakRef(T target, bool trackResurrection)
        {
            var handle = GCHandle.Alloc(target, trackResurrection ? GCHandleType.WeakTrackResurrection : GCHandleType.Weak);
            _ptr = GCHandle.ToIntPtr(handle);
        }

        [SecuritySafeCritical]
        ~WeakRef()
        {
            var ptr = _ptr;
            if ((ptr != IntPtr.Zero) && (ptr == Interlocked.CompareExchange(ref _ptr, IntPtr.Zero, ptr)))
            {
                var handle = GCHandle.FromIntPtr(ptr);
                handle.Free();
            }
        }

        public T Target
        {
            get
            {
                var ptr = _ptr;
                if (IntPtr.Zero != ptr)
                {
                    var target = GCHandle.FromIntPtr(ptr).Target;
                    if (_ptr != IntPtr.Zero)
                    {
                        return (T)target;
                    }
                }
                return null;
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

但我不确定我是否正确实施了BCL对手.有人能发现上面代码中的任何问题吗?

Kit*_*Kit 6

除了添加错误处理之外,我没有发现任何错误.但是,我更喜欢这个实现的简单性,特别是因为它使用BCL版本,你不必努力"正确":

public sealed class WeakReference<T> where T : class
{
    public WeakReference(T target) : this(target, trackResurrection)
    {}

    public WeakReference(T target, bool trackResurrection)
    {
        refTarget = new WeakReference(target, trackResurrection);
    }

    public T Target { get { return refTarget.Target as T; } }

    public bool IsAlive { get { return refTarget.IsAlive; }}

    private readonly WeakReference refTarget;
}
Run Code Online (Sandbox Code Playgroud)