Попытка понять реализацию Microsoft WeakReference

Как опытный программист на С++, пытающийся привыкнуть к .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, но, конечно же, не мог ли он быть удален и окончательно до того, как мы вернемся к возврату объекта? Я просто не могу найти обоснованное объяснение того, почему эта двойная проверка необходима здесь...

Ответ 1

Все, что я могу думать, это то, что, возможно, они пытаются защититься от WeakReference удаляется и завершается либо во время, либо после InternalGet

Это точно.

но, конечно же, он не мог быть удален и окончательно прежде чем мы вернемся к возврату объекта?

Нет, потому что в этот момент для объекта должен быть создан сильный указатель. InternalGet возвращает сильный указатель, и если этот сильный указатель, хранящийся в oldValue, относится к объекту, теперь объект больше не может быть возвращен сборщиком мусора.