Использование рекурсии в C#

Пожалуйста, обратитесь к , выпуск № 2665 , «версия с этим методом еще не опубликована на npm, используйте версию git».

16
задан Nifle 3 February 2010 в 23:00
поделиться

9 ответов

То, сколько раз Вы будете в состоянии рекурсивно вызвать, будет зависеть от:

  • размер стека (который обычно является 1 МБ IIRC, но двоичный файл может быть отредактирован рукой; я не рекомендовал бы делать так)
  • Сколько стека каждый уровень использования рекурсии (метод с 10 неполученными Guid, локальные переменные будут взятием больше стека, чем метод, который не имеет никаких локальных переменных, например)
  • JIT Вы используете - иногда, JIT будет хвостовая рекурсия использования, другие времена, это не будет. Правила являются сложными, и я не могу помнить их. (Существует сообщение в блоге David Broman назад с 2007 , и страница MSDN от того же автора/даты , но они могут устареть к настоящему времени.)

, Как избежать переполнений стека? Не рекурсивно вызывайте слишком далеко:), Если Вы не можете быть довольно уверены, что Ваша рекурсия завершится, не идя очень далеко (я был бы взволнован в "больше чем 10", хотя это очень безопасно) тогда переписывают его для предотвращения рекурсии.

32
ответ дан 30 November 2019 в 15:23
поделиться

Это действительно зависит, на каком рекурсивном алгоритме Вы используете. Если это - простая рекурсия, можно сделать что-то вроде этого:

public int CalculateSomethingRecursively(int someNumber)
{
    return doSomethingRecursively(someNumber, 0);
}

private int doSomethingRecursively(int someNumber, int level)
{
    if (level >= MAX_LEVEL || !shouldKeepCalculating(someNumber))
        return someNumber;
    return doSomethingRecursively(someNumber, level + 1);
}

стоит отметить, что этот подход действительно только полезен, где уровень рекурсии может быть определен как логический предел. В случае, что это не может произойти (такие как деление и завоевать алгоритм), необходимо будет решить, как Вы хотите сбалансировать простоту по сравнению с производительностью по сравнению с ограничениями ресурса. В этих случаях Вам, вероятно, придется переключиться между методами, как только Вы поражаете arbritrary предопределенный предел. Эффективное средство выполнения этого, что я использовал в quicksort алгоритме, должно сделать это как отношение общего размера списка. В этом случае логический предел является результатом того, когда условия больше не оптимальны.

8
ответ дан 30 November 2019 в 15:23
поделиться

Я не знаю ни о каком твердый набор для предотвращения stackoverflows. Я лично пытаюсь удостовериться -
1. Я имею свое основное право случаев.
2. Код достигает основного случая в какой-то момент.

7
ответ дан 30 November 2019 в 15:23
поделиться

Если Вы генерируете, что много стековых фреймов, Вы могли бы хотеть рассмотреть разворачивание Вашей рекурсии в цикл.

Особенно при выполнении нескольких уровней рекурсии (A-> B-> C-> A-> B...) Вы могли бы найти, что можно извлечь один из тех уровней в цикл и сохранить себя некоторая память.

4
ответ дан 30 November 2019 в 15:23
поделиться

Нормальный предел, если не много оставляют на стеке между последовательными вызовами, является приблизительно 15000-25000 уровнями глубоко. 25% из этого, если Вы находитесь на IIS 6 +.

Большая часть рекурсивного algorhitms может быть выражена многократно.

существует различный способ увеличить выделенное стековое пространство, но я скорее позволю Вам найти повторяющуюся версию сначала.:)

3
ответ дан 30 November 2019 в 15:23
поделиться

Кроме наличия разумного размера стека и проверки Вы делите и завоевываете свою проблему, таким образом, что Вы постоянно работаете над меньшей проблемой, не действительно.

1
ответ дан 30 November 2019 в 15:23
поделиться

Я просто думал о хвостовой рекурсии, но это сложилось, это, C# не поддерживает его. Однако Платформа.NET, кажется, поддерживает его:

http://blogs.msdn.com/abhinaba/archive/2007/07/27/tail-recursion-on-net.aspx

1
ответ дан 30 November 2019 в 15:23
поделиться

Размер стека по умолчанию для потока составляет 1 МБ, если Вы работаете под CLR по умолчанию. Однако другие хосты могут изменить это. Например, хост ASP изменяет значение по умолчанию на 256 КБ. Это означает, что у Вас может быть код, который работает отлично в соответствии с VS, но повреждается, когда Вы развертываете его на реальной среде хостинга.

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

можно отредактировать заголовок PE самого двоичного файла для изменения размера по умолчанию. Это полезно, если Вы хотите изменить размер для основного потока. Иначе я рекомендовал бы использовать соответствующего конструктора при создании потоков.

1
ответ дан 30 November 2019 в 15:23
поделиться

Помните, если необходимо спросить о системных пределах, тогда Вы, вероятно, делаете что-то ужасно неправильно.

Так, если Вы думаете, что могли бы получить переполнение стека в нормальном функционировании тогда, необходимо думать о другом подходе к проблеме.

не трудно преобразовать рекурсивную функцию в повторяющуюся, тем более, что C# имеет Дженерик:: набор Стека. Используя Стек тип перемещает память, используемую в "кучу" программы вместо стека. Это дает Вам диапазон полного адреса, чтобы хранить рекурсивные данные. Если это не достаточно, не слишком трудно разбить на страницы данные к диску. Но я серьезно рассмотрел бы другие решения, если Вы доходите до этой стадии.

0
ответ дан 30 November 2019 в 15:23
поделиться
Другие вопросы по тегам:

Похожие вопросы: