Как опытный программист на С++, пытающийся привыкнуть к .NET, есть деталь реализации в Microsoft WeakReference "Target" свойство, которое прослушивает меня...
public class WeakReference : ISerializable
{
internal IntPtr m_handle;
internal bool m_IsLongReference;
...
public virtual object Target
{
[SecuritySafeCritical]
get
{
IntPtr handle = this.m_handle;
if (IntPtr.Zero == handle)
{
return null;
}
object result = GCHandle.InternalGet(handle);
if (!(this.m_handle == IntPtr.Zero))
{
return result;
}
return null;
}
[SecuritySafeCritical]
set
{
IntPtr handle = this.m_handle;
if (handle == IntPtr.Zero)
{
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_HandleIsNotInitialized"));
}
object oldValue = GCHandle.InternalGet(handle);
handle = this.m_handle;
if (handle == IntPtr.Zero)
{
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_HandleIsNotInitialized"));
}
GCHandle.InternalCompareExchange(handle, value, oldValue, false);
GC.KeepAlive(this);
}
}
...
}
То, что меня беспокоит, - почему они дважды проверяют действительность m_handle? В частности, в методе "set" - использование GC.KeepAlive в конце метода должно удерживать WeakReference от сбора мусора и, таким образом, держать дескриптор ненулевым - правильно?
И в случае "get" - как только мы действительно получили ссылку на цель через InternalGet, зачем снова проверять исходное значение m_handle? Все, что я могу думать, это то, что, возможно, они пытаются защитить от WeakReference, который находится и завершен либо во время, либо после InternalGet, но, конечно же, не мог ли он быть удален и окончательно до того, как мы вернемся к возврату объекта? Я просто не могу найти обоснованное объяснение того, почему эта двойная проверка необходима здесь...