WeakReference в BCL был разработан в эпоху до появления дженериков, поэтому его интерфейс не так хорош, как мог бы быть. Также свойство 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;
}
}
}
но я не уверен, что правильно понял реализацию BCL.
Кто-нибудь может обнаружить какие-либо проблемы в коде выше?