自定义弱引用实现
BCL 中的 WeakReference 是在前泛型时代设计的,因此它的界面并没有想象中那么好。 IsAlive 属性也很容易被滥用。 通过 Reflector 查看 WeakReference 的实现,似乎我们可以自己实现它。 这是我想出的:
[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 对应项。 谁能发现上面代码中的任何问题吗?
WeakReference in BCL was designed in pre generics era, so it's interface is not as nice as it could be. Also IsAlive property is very easy to misuse.
Looking into the implementation of WeakReference trough Reflector it seems like we could implement it ourselves.
Here is what I came up with:
[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;
}
}
}
but I'm not sure I got the implementation of BCL counterpart right.
Can anyone spot any issues in the code above?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
除了添加错误处理之外,我没有立即发现任何错误。然而,我更喜欢这个实现,因为它简单,特别是因为它使用 BCL 版本,并且您不必努力“正确执行”:
I don't spot anything wrong offhand except adding error handling. However, I prefer this implementation for its simplicity, especially since it uses the BCL version and you don't have to try as hard to "get it right":
GCHandle
方法可能会引发异常 - 因此请确保您有try
/catches
。TryGetTarget
方法来鼓励更好的使用。WeakRef
?这是我的尝试。
GCHandle
methods could throw exceptions - so make sure you have yourtry
/catches
.TryGetTarget
method.WeakRef
?Here is my go at it.