Как возможна оптимизация хвостовой рекурсии в 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)
В основном, будьте осторожны с тем, что вы делаете со следами стека.