Как можно безопасно использовать делегат действия при удалении цели делегата - PullRequest
0 голосов
/ 17 декабря 2018

Я обычно использую делегат для обратного вызова.Например, я объявляю делегата Action в менеджере в скрипте Unity и регистрирую делегат при вызове OnEnable и отписываюсь при вызове OnDisable в моем производном от Monobehaviuor скрипте.Но я знал, что может быть опасно, если я буду сопротивляться и сопротивляться в неподходящее время.Например, если объект удален кем-то.цель делегата будет нулевой.Тогда нежелательный делегат обратного вызова может быть.Поэтому я хочу проверить, что цель делегата равна нулю, когда делегат оправдан, и я хочу удалить его, и я хочу, чтобы делегат уникально сопротивлялся, когда тот же делегат вызывался в том же сценарии.Как я могу использовать это безопасно?Вот мой пример источника.

класс менеджера

    public class TestManager : MonoBehaviour
{
    public Action TestDelegate;
    // Use this for initialization
    void Update ()
    {
        if (Input.GetKeyDown("space"))
        {
            if(null != TestDelegate)
            {  
                TestDelegate();
            }
        }
    }
}

класс объекта

public class WindosTest : MonoBehaviour {

    [SerializeField]
    TestManager _manager;   

    private void Awake()
    {   
        _manager.TestDelegate += Test;
    }

    // Update is called once per frame
    void Update ()
    {
        if (Input.GetKeyDown("d"))
        {
            GameObject.DestroyImmediate(this.gameObject);
        }
    }

    void Test()
    {
        UnityEngine.Debug.LogError("test");
    }
}

Ответы [ 2 ]

0 голосов
/ 17 декабря 2018

Проблема здесь в использовании DestroyImmediate вместо Destroy.Основное различие между этими двумя заключается в том, что Destroy требует правильной деконструкции объекта, что означает, что он получит свой обратный вызов OnDisable () до того, как будет уничтожен (так что у него есть шанс отписаться от делегатов).

Обычно (не в редакторе) лучше вызывать Destroy () вместо DestroyImmediate () из-за безопасности.

Если вы вызываете Destroy (), вы получите нормальный обратный вызов OnDisable, что означает, что вы можете сделать:

void OnEnable()
{   
    _manager.TestDelegate += Test;
}
void OnDisable()
{   
    _manager.TestDelegate -= Test;
}
0 голосов
/ 17 декабря 2018

вы уже делаете это, если только я неправильно понял вопрос

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

TestDelegate?.Invoke();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...