Вот вопрос, чтобы раскрыть мой недостаток опыта: у меня есть метод Сделай что-нибудь(), который выдает исключение, если ему не удается сделать это чисто. Если это не удается, я несколько раз пробую менее точный метод DoSomethingApproximately () в надежде, что он найдет достаточно хорошее решение; если это тоже не удается, я, наконец, вызываю DoSomethingInaccurateButGuaranteedToWork (). Все три являются методами, принадлежащими этому объекту.
Два вопроса: во-первых, приемлем ли этот (по общему признанию уродливый) шаблон, или есть более элегантный способ?
Во-вторых, как лучше всего отслеживать, сколько раз я вызывал DoSomethingApproximately (), учитывая, что это может вызвать исключение? В настоящее время я храню в объекте переменную iNoOfAttempts и вкладываю блоки try ... это ужасно, и мне стыдно.


Вернуть код ошибки вместо создания исключения.
Если способы отказа этих методов вызывают исключения, перехватите их все в одном методе и выполните соответствующие действия, например, увеличьте счетчик и верните код ошибки.
bool result = DoSomething();
while (!result && tries < MAX_TRIES) {
result = DoSomethingApproximately(); //This will increment tries
if (tries > THRESHOLD) {
result = DoSomethingThatAlwaysWorks();
}
}
Вы никогда не должны использовать исключения для потока управления вашего приложения.
В вашем случае я бы объединил три метода в один метод, и он вернул бы, какой конкретный подход был успешным, возможно, с перечислением или чем-то в этом роде.
Я не согласен. если DoSomethingApproximately () и DoSomethingThatAlwaysWorks () на самом деле являются функциями обработки ошибок, то исключения вполне могут быть подходящим способом для этого.
Исключения должны возникать в неожиданных ситуациях, а не в ожидаемых ошибках. Конечно, из этого правила тоже есть исключения.
Да, конечно. Мы должны предположить, что DoSomething () делает то, что должен делать, если только не произойдет что-то неожиданное ...;)
Нет, мы не должны ничего предполагать. Спрашивающий даже, кажется, ожидает, что метод потерпит неудачу ...
Кроме того, вы должны быть осторожны, чтобы не скрывать исключения, которые являются реальными проблемами, а не «ожидаемыми» проблемами. Тем не менее, +1 не использует исключения для управления потоком.
Я только очень редко ожидаю, что это случится. Но я понимаю, что такое управление потоком.
Как насчет (псевдокода):
try{ return doSomething(); }
catch(ExpectedException) { ...not much here probably...}
for(i = 0 to RETRIES){
try{ return doSomethingApproximately; }
catch(ExpectedException) { ...not much here probably...}
}
doSomethingGuaranteed();
Дополнение:
Я настоятельно рекомендую вам не использовать специальные возвращаемые значения, потому что это означает, что каждый отдельный пользователь функции должен знать, что некоторые из возвращаемых значений являются особенными. В зависимости от диапазона функции может быть разумным возвращать обычную часть диапазона, с которой можно нормально работать, например пустая коллекция. Конечно, это может сделать невозможным различие между ошибкой и «правильным» ответом, являющимся пустой коллекцией (в этом примере).
Иногда мне нравится иметь параметр, позволяющий вызывающему абоненту указывать, следует ли указывать общие режимы отказа через исключение или код возврата. Рассмотрим что-то вроде «войти на сервер X с учетными данными Y». Если вызывающий абонент ожидает, что попытка может потерпеть неудачу (например, если у него есть список серверов, и он будет пытаться, пока не добьется успеха), использование метода исключения исключения бесполезно. С другой стороны, если код ожидает, что логин будет просто работать, генерирование исключения может устранить необходимость проверки ошибок на стороне клиента при попытке, если возникшее исключение будет тем, которое клиент может уловить.
Переместите все указатели функций в маршрут структуры. Чтобы оживить его, я воспользуюсь очередью и немного LINQ.
Queue<Action> actions = new Queue<Action>(new Action[] {
obj.DoSomething,
obj.DoSomethingApproximately,
obj.DoSomethingApproximately,
obj.DoSomethingApproximately,
obj.DoSomethingApproximately,
obj.DoSomethingGuaranteed
});
actions.First(a => {
try {
a();
return true;
} catch (Exception) {
return false;
}
});
Да; Я предполагаю, что большинство решений должны быть в значительной степени независимыми от языка, если возможна обработка исключений.