Функциональный C # - использование или возврат действий - PullRequest
3 голосов
/ 27 октября 2010

Просматривая сеть для лучшей обработки ошибок в C #, я ознакомился со следующими стратегиями реализации.Первая для меня естественна, а в другой реализации я не уверен, в чем ее преимущества?

1) static void Fault(Action protectedBlock, Action faultHandler) { try { protectedBlock(); } catch { faultHandler(); throw; }<br> }

2)

</p> <pre> static Action Fault(Action protectedBlock, Action faultHandler) { return () => { try { protectedBlock(); } catch { faultHandler(); throw; } }; } </pre> <p>

Является ли 2) предпочтительной стратегией при разработке функций высшего порядка в C #?

И мне интересно, если один подход более эффективен, чем другой.

Ответы [ 3 ]

5 голосов
/ 27 октября 2010

Второй случай похож на Faultable Action Factory. Где вы передаете делегат того, что вы хотите сделать, protectedBlock, и делегат того, что делать, когда происходит Exception, faultHandler. Действия возвращаются в виде структуры try / catch в виде совокупности Action. Моя проблема с обоими этими методами заключается в том, что Exception на самом деле не пойман, поэтому у тех, кто собирается поймать ваш бросок, нет информации о том, как действовать.

Разница в исполнении между двумя заключается в том, когда они фактически выполняются. 1-й будет выполнен, когда он будет вызван. 2-й будет выполняться всякий раз, когда вызывается возвращенный Action. Я не думаю, что разница в эффективности была бы значительной.

4 голосов
/ 27 октября 2010

(2) может быть дополнительно составлено, в то время как (1) просто выполняется. Но ни один из них не является «функциональным», так как Action не является функцией (сравните с Func<A, R>).

Итак, с (2) вы можете сделать:

Fault(someAction, Fault(firstTryFaultHandler, lastDitchFaultHandler))();

... и получите ожидаемое поведение. Это не работает с (1)

1 голос
/ 27 октября 2010

В C # подход 2 может сбивать с толку.Вызывающий может использовать «Ошибка (а, б);»ожидая, что и, возможно, будет вызван b.Вместо этого лямбда создается, возвращается и отбрасывается.Другими словами, ничего не делается.

Что касается эффективности, подход 2 немного расточителен, если большинство ваших вызовов имеют форму "Fault (a, b) ();", то есть вы немедленно вызываете лямбду.В этой ситуации вам не нужна лямбда.

По этим причинам я бы предпочел подход 1. Если вам нужно отложить выполнение, вы можете явно ввести лямбду "() => Fault (a,б)».

...