Шаблон для попытки различных методов при возникновении исключения - PullRequest
3 голосов
/ 24 сентября 2008

Вот вопрос, чтобы показать мой недостаток опыта: у меня есть метод DoSomething () , который выдает исключение, если ему не удается сделать это чисто. В случае неудачи я несколько раз пытаюсь использовать менее точный метод DoSomethingApproximately () в надежде найти достаточно хорошее решение; если это также не удается, я наконец вызываю DoSomethingInaccurateButGuaranteedToWork () . Все три метода принадлежат этому объекту.

Два вопроса: во-первых, приемлем ли этот (по общему признанию, уродливый) шаблон или есть более элегантный способ?

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

Ответы [ 4 ]

4 голосов
/ 24 сентября 2008

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

В вашем случае я бы объединил три метода в один метод и вернул, какой конкретный подход был успешным, может быть с перечислением или чем-то в этом роде.

2 голосов
/ 24 сентября 2008

Перейдите целые указатели функций в структуре маршрута. Просто чтобы оживить его, я буду использовать Очередь и немного 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;
   }
});
2 голосов
/ 24 сентября 2008

Как насчет (псевдокод):

try{ return doSomething(); }
catch(ExpectedException) { ...not much here probably...}

for(i = 0 to RETRIES){
try{ return doSomethingApproximately; }
catch(ExpectedException) { ...not much here probably...}
}

doSomethingGuaranteed();

Добавление:

Я настоятельно рекомендую не использовать специальные возвращаемые значения, поскольку это означает, что каждый пользователь функции должен знать, что некоторые возвращаемые значения являются специальными. В зависимости от диапазона функции может быть целесообразно вернуть обычную часть диапазона, с которой можно иметь дело обычно, например, пустая коллекция. Конечно, это может сделать невозможным различие между ошибкой, и «правильным» ответом является пустая коллекция (в этом примере).

2 голосов
/ 24 сентября 2008

Возвращать код ошибки, а не выдавать исключение.

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

   bool result = DoSomething();
   while (!result && tries < MAX_TRIES) {
       result = DoSomethingApproximately(); //This will increment tries
       if (tries > THRESHOLD) {
           result = DoSomethingThatAlwaysWorks();
       }
   }
...