Как возможна оптимизация хвостовой рекурсии в C# при возврате трассировки стека при возникновении исключения

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

1 ответ

Решение

Ну, это имеет значение, только если вы ожидаете получить точную трассировку стека:)

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

Вот очень простой пример именно этой проблемы:

using System;
using System.Runtime.CompilerServices;

class Program
{
    static void Main(string[] args)
    {
        try
        {
            Call1();
        }
        catch (Exception e)
        {
            Console.WriteLine(e.StackTrace);
        }
    }

    static void Call1()
    {
        Call2();
    }

    static void Call2()
    {
        Call3();
    }

    [MethodImpl(MethodImplOptions.NoInlining)]
    static void Call3()
    {
        Call4();
    }

    static void Call4()
    {
        Call5();
    }

    static void Call5()
    {
        throw new Exception();
    }
}

Постройте и запустите без отладчика, и вы можете получить это:

at Program.Call3()
at Program.Main(String[] args)

В основном, будьте осторожны с тем, что вы делаете со следами стека.

Другие вопросы по тегам