Как вызвать sub, который вызвал этот sub из будущего sub

#vb.net #class #stack-trace

#vb.net #класс #трассировка стека

Вопрос:

Мальчик, о, мальчик, это название сбивает с толку, да!

Это лучше всего объяснить на примере.. вот что я хочу, чтобы произошло.

 Dim m as sub

Public sub alg1()
    call alg2()
End sub

Public sub alg2()
    m = alg1
    call alg3()
End sub

Public sub alg3()
    call m
End sub
  

Итак, я начинаю запускать свой код в alg1. alg1 вызывает alg2, в котором указывается, кто его вызвал (я думаю, с помощью stackTrace.GetFrame(1) .GetMethod().Name), а затем сохраняет это в локальной переменной, а затем alg2 переходит к вызову alg3. alg3 вызывает тот sub, который хранится в локальной переменной m .

Теперь моя ситуация немного сложнее, поскольку alg1 находится в другом классе, чем alg2, но теоретически все, что я пытаюсь сделать, это выполнить межклассовый вызов sub, который определен во время выполнения. Есть ли какой-нибудь способ сохранить sub таким образом?

Комментарии:

1. Понижение в течение первых 30 секунд.. это должна быть какая-то запись. Любые советы о том, как улучшить вопрос (или почему он был отклонен)?

2. посмотрите на делегатов. msdn.microsoft.com/en-us/library/ms172880.aspx и msdn.microsoft.com/en-us/library/5t38cb9x.aspx

3. Если alg1 и alg2 находятся в разных классах, где alg3? Даже если вы знаете функцию, вам все равно понадобится ссылка на объект. Можете ли вы передать их в качестве аргументов? В вашем примере у вас будет бесконечный цикл, как вы из него выйдете? Не могли бы вы сделать это с помощью events и вместо этого делегировать?

4. @Jeremy спасибо, похоже, это то, что я ищу, я все еще немного не понимаю, как я могу использовать их для своих целей… но я думаю, мне просто нужно какое-то время обдумывать это!

5. по сути, вы можете использовать переменную для вызова функции, поэтому вам нужно передать переменную делегата в функцию, чтобы вызвать ее позже. Есть ли у вас описание более высокого уровня реальной проблемы, которую вы пытаетесь решить? Возможно, вы смотрите на это неправильно.

Ответ №1:

Ваш пример должен работать с небольшим изменением Action и AddressOf

 Dim m As Action

Public Sub alg1()
    Call alg2()
End Sub

Public Sub alg2()
    m = AddressOf alg1
    Call alg3()
End Sub

Public Sub alg3()
    Call m()
End Sub
  

Другой вариант — передать его в качестве параметра:

 Public Sub alg2()
    alg3(AddressOf alg1)
End Sub

Public Sub alg3(m As action)
    m()
End Sub
  

Ответ №2:

Вот краткий пример, в котором реализована идея, описанная выше.

Упрощенный консольный код:

 Public Module Module1

    Private Delegate Sub CoolDelegate()
    Private m As CoolDelegate

    Public Sub Main()
        Debug.WriteLine("Calling Alg1")
        Alg1()
    End Sub

    Private Sub Alg1()
        Debug.WriteLine("Alg1 Called")

        Debug.WriteLine("Calling Alg2")
        Alg2()
    End Sub

    Private Sub Alg2()
        Debug.WriteLine("Alg2 Called")

        m = New CoolDelegate(AddressOf Alg1)
        Debug.WriteLine("Calling Alg3")
        Alg3()
    End Sub

    Private Sub Alg3()
        Debug.WriteLine("Alg3 Called")

        Debug.WriteLine("Calling m")
        m()
    End Sub
End Module
  

Вывод:

 Calling Alg1
Alg1 Called
Calling Alg2
Alg2 Called
Calling Alg3
Alg3 Called
Calling m
Alg1 Called
Calling Alg2
Alg2 Called
Calling Alg3
Alg3 Called
Calling m
Alg1 Called
Calling Alg2
Alg2 Called
Calling Alg3
Alg3 Called
Calling m
Alg1 Called
Calling Alg2
  

(… Повторяется до переполнения стека …)

Его также можно изменить, чтобы избавиться от локальной частной переменной. Вот еще одна версия…

 Public Module Module1

    Private Delegate Sub CoolDelegate()

    Public Sub Main()
        Debug.WriteLine("Calling Alg1")
        Alg1()
    End Sub

    Private Sub Alg1()
        Debug.WriteLine("Alg1 Called")

        Debug.WriteLine("Calling Alg2")
        Alg2(AddressOf Alg1)
    End Sub

    Private Sub Alg2(Caller As CoolDelegate)
        Debug.WriteLine("Alg2 Called")

        Debug.WriteLine("Calling Alg3")
        Alg3(Caller)
    End Sub

    Private Sub Alg3(Caller As CoolDelegate)
        Debug.WriteLine("Alg3 Called")

        Debug.WriteLine("Calling Caller")
        Caller()
    End Sub
End Module