Найпростіше пояснення рекурсії в C#

Алгоритми рекурсії не дуже популярні в продукційному коді. Головна причина — рекурсія має чимало обмежень. Але якщо вона вам потрібна, ви повинні чітко розуміти, як вона працює, та як уникнути можливих обмежень.

Рекурсія в C# — це метод, який викликає сам себе прямо або опосередковано для вирішення задачі. Це чітке визначення, але як розробник, чи впевнені ви, що розумієте, як це працює?

Давайте розглянемо класичний приклад реалізації рекурсії — обчислення факторіала.
Код виглядатиме ось так:

long Factorial(int n)  
{  
 if (n == 0)  
 return 1;  
 return n * Factorial(n - 1);  
}

У C# рекурсія залежить від стеку викликів для відстеження контексту кожного рекурсивного виклику.

Кожен виклик створює фрейм стека:
Кожного разу, коли метод викликає сам себе рекурсивно, стан методу (локальні змінні, параметри, адреса повернення) додається до стеку викликів.

Ви будете множити всі числа від N до 1 (коли N = 0, ми повернемо 1).

Для візуалізації можна використовувати вікно Call Stack у Visual Studio:

pic

Вікно Call Stack у Visual Studio

Але приклад з факторіалом не зовсім наочно показує всю інформацію в стеці викликів, оскільки він занадто простий.

Розглянемо приклад функції IsEven:

bool IsEven(int x)  
{  
 if (x == 0)  
 return true;  
 if (IsEven(x - 1))  
 {  
 return false;  
 }  
 else  
 {  
 return true;  
 }  
}

Вікно Call Stack покаже таку інформацію, якщо ми перевіримо результат для X=7:

pic

Вікно Call Stack у Visual Studio

Для X=0 ми завжди повертаємо true, оскільки це парне число.
Для інших кожен виклик залежатиме від наступного виклику в стеці викликів.

Діаграма виглядатиме ось так:

pic

Діаграма для функції Is Even, коли X=7

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

У сценаріях, де використовується рекурсія, моніторинг глибини рекурсивних викликів може бути критично важливим, особливо для запобігання помилок переповнення стека або проблем із налагодженням. C# надає клас StackTrace, який дозволяє вам перевіряти поточний стек викликів. Цей клас можна використовувати для програмного відстеження і логування глибини рекурсії, що дає уявлення про потік виконання рекурсивних методів. Однак використовувати його слід обережно, оскільки надмірна перевірка стека може вплинути на продуктивність у випадках глибокої рекурсії.

Успіхів у програмуванні!

Перекладено з: Easiest explanation of recursion in C#

Leave a Reply

Your email address will not be published. Required fields are marked *