Слабые ссылки и устранение циклов (C++/CX)Weak references and breaking cycles (C++/CX)

В любой системе типов, которая основана на подсчете ссылок, ссылки на типы могут сформировать циклы, т. е. может возникнуть ситуация, когда один объект ссылается на второй объект, второй объект ссылается на третий объект, и так далее до тех пор, пока некоторый последний объект не будет ссылаться на первый объект.In any type system that's based on reference-counting, references to types can form cycles—that is, one object refers to a second object, the second object refers to a third object, and so on until some final object refers back to the first object. В цикле объекты невозможно правильно удалить, если количество ссылок одного из объектов становится равным нулю.In a cycle, objects can't be deleted correctly when one object's reference count becomes zero. Чтобы помочь вам решить эту проблему, C++/CX предоставляет класс класса Platform:: WeakReference .To help you solve this problem, C++/CX provides the Platform::WeakReference Class class. Объект WeakReference поддерживает метод Resolve , который возвращает значение NULL, если объект больше не существует, или исключение Platform::InvalidCastException , если объект существует, но его тип отличается от T.A WeakReference object supports the Resolve method, which returns null if the object no longer exists, or throws an Platform::InvalidCastException if the object is alive but is not of type T.

Один из сценариев, в котором WeakReference следует использовать, — это когда this указатель захватывается в лямбда-выражении, которое используется для определения обработчика событий.One scenario in which WeakReference must be used is when the this pointer is captured in a lambda expression that's used to define an event handler. Рекомендуется использовать при определении обработчиков событий именованные методы, но если необходимо использовать для обработчика событий лямбда-выражения или если необходимо нарушить цикл подсчета ссылок, используйте класс WeakReference.We recommend that you use named methods when you define event handlers, but if you want to use a lambda for your event handler—or if you have to break a reference counting cycle in some other situation—use WeakReference. Ниже приведен пример:Here's an example:


using namespace Platform::Details;
using namespace Windows::UI::Xaml;
using namespace Windows::UI::Xaml::Input;
using namespace Windows::UI::Xaml::Controls;

Class1::Class1()
{
    // Class1 has a reference to m_Page
    m_Page = ref new Page();

    // m_Page will have a reference to this Class1
    // so create a weak reference to this
    WeakReference wr(this);
    m_Page->DoubleTapped += ref new DoubleTappedEventHandler(
        [wr](Object^ sender, DoubleTappedRoutedEventArgs^ args)
    {
       // Use the weak reference to get the object
       Class1^ c = wr.Resolve<Class1>();
       if (c != nullptr)
       {
           c->m_eventFired = true;
       }
       else
       {
           // Inform the event that this handler should be removed
           // from the subscriber list
           throw ref new DisconnectedException();
       }
    });
}

}

Когда обработчик событий создает исключение DisconnectedException, событие удаляет обработчик из списка подписчиков.When an event handler throws DisconnectedException, it causes the event to remove the handler from the subscriber list.