Почему действие обратного вызова указывает на метод, отличный от назначенного? - PullRequest
0 голосов
/ 07 ноября 2019

Я пытаюсь передать метод с параметрами в качестве действия обратного вызова. Мой подход заключается в назначении действия обратного вызова через делегата. Однако когда я вызываю обратный вызов, метод, который я использовал в делегате, не вызывается. Вместо этого вызывается метод, в котором я объявил обратный вызов. Почему это так?

Я уже использовал этот подход много раз, и он всегда работал по назначению.

На рисунке ниже я бы ожидал, что имя метода обратного вызова будет "OnPhaseFinished"вместо "StartCurrentPhase":

enter image description here

1 Ответ

2 голосов
/ 07 ноября 2019

Давайте поместим ваш код в SharpLab и посмотрим, что генерирует компилятор.

Я использую этот код, который приблизительно соответствует коду в вашем вопросе:

using System;
public class C {
    private Phase _currentPhase;

    private void StartCurrentPhase()
    {
        Action callback = delegate { OnPhaseFinished(_currentPhase); };
        _currentPhase.Activate(callback);
    }

    private void OnPhaseFinished(Phase currentPhase)
    {
    }
}

public class Phase
{
    public void Activate(Action callback) { }
}

Затем компиляторгенерирует:

public class C
{
    private Phase _currentPhase;

    private void StartCurrentPhase()
    {
        Action callback = new Action(<StartCurrentPhase>b__1_0);
        _currentPhase.Activate(callback);
    }

    private void OnPhaseFinished(Phase currentPhase)
    {
    }

    [CompilerGenerated]
    private void <StartCurrentPhase>b__1_0()
    {
        OnPhaseFinished(_currentPhase);
    }
}
public class Phase
{
    public void Activate(Action callback)
    {
    }
}

Смотрите здесь на SharpLab

Вы можете видеть, что компилятор превратил ваш delegate { OnPhaseFinished(_currentPhase); }; в приватный метод класса C:

private void <StartCurrentPhase>b__1_0()
{
    OnPhaseFinished(_currentPhase);
}

Затем создается экземпляр делегата Action, указывающий на этот сгенерированный метод <StartCurrentPhase>b__1_0.

Таким образом, компилятор реализует анонимные делегаты (и лямбды): путем созданияновый закрытый метод (иногда в текущем классе, но иногда в совершенно новом классе).

Получилось так, что он назвал метод <StartCurrentPhase>b__1_0, созданный после имени метода, который содержит анонимный делегат,но это полностью его решение - он мог бы назвать его как угодно.

Это не означает, что вызов делегата каким-то образом вызывает метод StartCurrentPhase. Вы можете видеть, что он вызывает метод <StartCurrentPhase>b__1_0 (который отличается от до StartCurrentPhase), который в свою очередь вызывает OnPhaseFinished(_currentPhase);.

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