BCL中的WeakReference是在pre-generics时代设计的,所以它的界面并不尽如人意. IsAlive属性也很容易被误用.
查看WeakReference槽Reflector的实现,我们似乎可以自己实现它.
这是我想出的:
查看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; } } }
但我不确定我是否正确实施了BCL对手.
有人能发现上面代码中的任何问题吗?
解决方法
除了添加错误处理之外,我没有发现任何错误.但是,我更喜欢这个实现的简单性,特别是因为它使用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; }