Если вы хотите сделать что-то умное / злое, вы можете использовать ключевое слово when
, чтобы ввести ведение журнала без прерывания трассировки стека в вашем исключении.
См. , когда контекстное ключевое слово в ссылке C # на MSDN. Предполагается, что он будет использоваться в качестве фильтра (метод возвращает значение true или false, указывающее, следует ли использовать этот блок catch), но вы можете делать все, что захотите, с помощью
Я думаю, что это то, что вы хотите, хотя Я не проверял это:
public void someFunction(object data)
{
try
{
var response = await request(data);
LogInformation(request: data, response: response);
}
catch (Exception e) when (HandleAndLogException(data, e))
{
throw;
}
}
private bool HandleAndLogException(object data, Exception e)
{
LogException(data: data, response: e.Message);
return true;
}
Я думаю, что этот вопрос отражает много способов освежевать кошку. Я нахожу делегатов (и лямбды) почти столь же фундаментальный как "для" цикла.
Вот один контекст, в котором я недавно использовал делегатов (форматирование и имена, изменившие в целях презентации:)
protected T[] SortLines<T>(Func<T> createLine, IEnumerable<T> unsorted)
where T : LineType
{
Func<IEnumerable<T>, IEnumerable<T>> sorter = (lines => lines);
switch (settings.OrderSort)
{
case OrderSort.ByA:
sorter = (lines => lines.OrderBy(x => x.A)); break;
case OrderSort.ByB:
sorter = (lines => lines.OrderBy(x => x.B)); break;
// and so on... a couple cases have several levels of ordering
}
bool requiresSplit = // a complicated condition
if (requiresSplit)
{
var positives = unsorted.Where(x => x.Qty >= 0);
var negatives = unsorted.Where(x => x.Qty < 0);
return sorter(negatives).Concat(
new T[] { createLine.Invoke() }).Concat(
sorter(positives)).ToArray();
}
else
return sorter(unsorted).ToArray();
}
Таким образом, это сортирует группу объектов на основе некоторых критериев и затем этого или возвращает целый список, отсортированный, или это повреждает его в два, виды обе половины отдельно, и помещает разделитель, промежуточный их. Удача, делающая это изящно, если Вы не можете выразить понятия "способа отсортировать что-то", которое является тем, для чего делегат.
Править: Я предполагаю Concat, и OrderBy конкретны для 3.0, но это - все еще основная идея.
Кроме GUI...
К моему знанию делегат.NET является по существу реализацией интерфейса отдельного метода без всей шумихи объявления класса. Мне жаль, что у нас не было их в Java, лично. Думайте о классе компаратора:
class MyComparator<Circle> extends Comparator<Circle> {
public int compare(Circle a, Circle b) {
return a.radius - b.radius;
}
}
Везде этот шаблон полезен, делегат мог быть полезным вместо этого.
Я надеюсь, что я прав, но разрешение и проваливает меня, если я неправ; это было слишком длинно, так как я видел любой C# :)
Другое большое использование делегатов как конечные автоматы. Если Ваша логика программы содержит повторенный, если... затем операторы для управления, что указывает, это находится в, или если Вы используете сложные блоки переключателя, можно легко использовать их для тиражирования шаблона состояния.
enum State {
Loading,
Processing,
Waiting,
Invalid
}
delegate void StateFunc();
public class StateMachine {
StateFunc[] funcs; // These would be initialized through a constructor or mutator
State curState;
public void SwitchState(State state) {
curState = state;
}
public void RunState() {
funcs[curState]();
}
}
Мои 2,0 синтаксиса делегата могут быть ржавыми, но это - довольно простой пример диспетчера состояния. Также помните, что делегаты в C# могут выполнить больше чем одну функцию, позволив Вам иметь конечный автомат, который выполняет произвольно много функций каждый RunState ().
В любое время при выполнении любых асинхронных операций, таких как совершение звонков веб-сервиса, можно использовать делегата поэтому, когда вызов возвращается, можно инициировать делегата, призывают, чтобы цель обработала вещи.
Делегаты становятся чрезвычайно мощными, когда Вы начинаете смотреть на них как на функциональные конструкции
.Net 2.0 включал поддержку анонимных делегатов, которые сформировали ядро некоторых функциональных понятий, на которых подробно остановился Linq. Синтаксис для анонимного делегата является немного более большим, чем, какое предложение Лямбды, но много базовых функциональных шаблонов находится там в 2,0.
В Списке универсальный тип у Вас есть следующие объекты, с которыми можно работать:
Appart из Списка определенные объекты, когда Ваш использующий анонимный контекст делегатов обрабатывается правильно, таким образом, можно реализовать Закрытие как структуры. Или, на большем practicle уровне делают что-то как:
ILog logger = new Logger();
MyItemICareAbout.Changed += delegate(myItem) { logger.Log(myItem.CurrentValue); };
И это просто работает.
Существует также материал DynamicMethod, который позволяет Вам определять биты IL (использующий Отражение. Испустите), и скомпилируйте их как делегатов. Это дает Вам хорошую альтернативу чистому отражению для вещей как Отображающиеся слои и код доступа к данным.
Делегаты являются действительно конструкцией, которая позволяет Вам представлять исполняемый код как данные. После того как Вы получаете голову вокруг того, что это означает, существует много вещей, которые могут быть сделаны. Поддержка этих конструкций в 2,0 была элементарной по сравнению с 3,5, но все еще там, и все еще довольно мощной.
Делегаты часто используются для отправки события, однако это - то, только потому, что они удобны, чтобы сделать так. Делегаты полезны для любого вида вызова метода. У них также есть много дополнительных функций, таких как способность вызвать асинхронно.
Основная причина делегата, хотя должен обеспечить Закрытие или способность вызвать функцию наряду с, он - состояние, которое обычно является экземпляром объекта.
Один общий шаблон, который я видел за эти годы (на различных языках) должен "заморозить" результат решения переместить логику из цикла в установку. В псевдокоде (потому что техника меняется в зависимости от языка):
some_condition = setup_logic
...
while (not terminated) {
data = obtain_data
if (some_condition)
process_one (data)
else
process_two (data)
}
Дело в том, что, если some_condition
не изменяется на основе ничего в цикле, затем нет действительно никакого преимущества от повторного тестирования его. Делегаты/закрытия/и т.д. позвольте вышеупомянутому быть замененным этим:
some_condition = setup_logic
if (some_condition)
selected_process = process_one
else
selected_process = process_two
...
while (not terminated) {
data = obtain_data
selected_process (data)
}
(Конечно, Настоящий Функциональный Программист записал бы установку как:
selected_process = if (some_condition) process_one else process_two
;-)
Это делает вывод приятно к нескольким альтернативам (вместо всего два). Ключевая идея состоит в том, чтобы решить заранее, какие меры принять в моменте в будущем (или точки) и затем помнить выбранное действие, а не значение, на котором базировалось решение.