2008-10-06 3 views
3

Об этом говорится в an interesting post over here, касающемся сквозного потока управления.Исключения для управления потоком

Ну, в последнее время я столкнулся с интересной проблемой. Генерация n-го значения в потенциально (практически) бесконечной рекурсивной последовательности. Этот конкретный алгоритм будет находиться по меньшей мере в 10-15 ссылках на стопки в той точке, в которой он преуспевает. Моя первая мысль была бросить SuccessException, который выглядел что-то вроде этого (C#):

class SuccessException : Exception 
{ 
    public string Value 
    { get; set; } 

    public SuccessException(string value) 
     : base() 
    { 
     Value = value; 
    } 
} 

Затем сделать что-то вроде этого:

try 
{ 
    Walk_r(tree); 
} 
catch (SuccessException ex) 
{ 
    result = ex.Value; 
} 

Тогда мои мысли блуждали назад здесь, где я слышал над и никогда не использовать Исключения для управления потоком. Есть ли оправдание? И как бы вы структурировали нечто подобное, если бы вы его реализовали?

ответ

5

В этом случае я бы посмотрел на ваш метод Walk_r, вы должны иметь что-то, что возвращает значение, бросая исключение для указания успеха, НЕ является обычной практикой и, как минимум, будет ОЧЕНЬ смущать любого, кто видит код. Не говоря уже о накладных расходах, связанных с исключениями.

+0

По сравнению с накладными расходами для определения значения успеха на каждом уровне и выхода из 10+ ссылок на стопки? Что касается использования, это персональный проект, а не то, что я предполагаю. – 2008-10-06 14:24:22

+0

Если у вас более 10 ссылок на стопку и глубокая обработка ошибок, инфраструктура должна в любом случае сделать кучу дополнительной обработки. Если вы настроите рекурсивные вызовы для возврата успешного значения, это не должно быть проблемой. – 2008-10-06 14:27:23

+0

Достаточно. Другая половина вопроса заключалась в том, как я мог бы структурировать это по-другому. Возможно, как «bool Walk_r (дерево объектов, результат строки)»? – 2008-10-06 14:29:45

0

Это не очень хорошая идея, чтобы генерировать исключения как часть алгоритма, особенно в .net. На некоторых языках/платформах исключения довольно эффективны при броске, и обычно они возникают, когда итерируемый, например, исчерпан.

0

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

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

0

Проблема с использованием исключений заключается в том, что tey (в большой схеме вещей) очень неэффективны и медленны. Разумеется, было бы легко иметь условие if в рекурсивной функции, чтобы просто возвращать по мере необходимости. Честно говоря, с объемом памяти на современных ПК его маловероятным (хотя и невозможным), что вы получите переполнение стека с небольшим количеством рекурсивных вызовов (< 100).

Если стек является реальной проблемой, тогда может возникнуть необходимость быть «креативным» и реализовать «стратегию поиска с ограниченным доступом», позволить функции вернуться из рекурсии и возобновить поиск с последней (самой глубокой) узел.

Подводя итог: Исключения должны использоваться только в исключительных обстоятельствах, успех вызова функции, который, как я полагаю, не квалифицируется как таковой.

0

Использование исключений в нормальном потоке программы в моей книге является одним из худших практик когда-либо. Рассмотрите бедного сока, который охотится за проглоченными исключениями и запускает отладчик, установленный для остановки всякий раз, когда происходит исключение. Этот чувак теперь злится ... и у него есть топор. : P

1

Функция walk_r должна просто вернуть значение при его ударе. Это довольно стандартный пример рекурсии. Единственная потенциальная проблема, которую я вижу, заключается в том, что вы сказали, что она потенциально бесконечна, и ее нужно будет компенсировать в коде walk_r, сохраняя подсчет глубины рекурсии и останавливаясь при некотором максимальном значении.

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

try 
{ 
    Walk_r(tree); 
} 
catch (SuccessException ex) 
{ 
    result = ex.Value; 
} 

становится

result = Walk_r(tree); 
0

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

Смежные вопросы