Попытка понять реализацию Microsoft WeakReference - PullRequest
10 голосов
/ 29 декабря 2011

Как опытный программист C ++, пытающийся привыкнуть к .NET, есть деталь реализации в свойстве WeakReference от Microsoft "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 Ответ

8 голосов
/ 29 декабря 2011

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

Совершенно верно.

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

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

...