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?
When a weak reference A is created to an object B, there would be an entry in the hashtable modified or created, whose key would be the pointer to B. "Dirty" - to store a special hash-value with each object, which would be zeroed when the object is destroyed.
WeakReference and SoftReference are used when you want to keep something around in case you need it again - but you might not need it and if you do need it you can recreate it.
A weak reference permits the garbage collector to collect the object while still allowing the application to access the object. A weak reference is valid only during the indeterminate amount of time until the object is collected when no strong references exist.
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":
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;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With