Слепо вызывать функции, ловить и обрабатывать исключения или писать код, чтобы предотвратить выполнение функции, которая выдает исключение

1

Поэтому мне было интересно, что лучше делать, когда дело касается исключений, которые могут быть брошены в ваш код.

Скажем, например, у меня есть список предметов. Должен ли я проверить, существует ли элемент в 'i', прежде чем я попытаюсь получить к нему доступ? (Если list.Count> i), или я должен просто запустить код, и поймать исключение, если оно будет выбрано?

Я всегда делал первое, где я бы писал проверки, чтобы гарантировать, что функции не будут вызваны, если бы я знал, что это будет исключать. (Проверки границ, нулевые проверки и т.д.). Но теперь, когда я действительно об этом думаю, разве я не удваиваю код? Класс List уже проверяет ограничения для меня, и он выбрасывает соответствующие исключения. Почему я тоже делаю оценку? Я мог бы просто сохранить себе работу, слепо вызвать функцию, поймать исключение и действовать соответствующим образом.

Какой путь "правильнее"?

  • 0
    Обработка исключений всегда дорогая. Поэтому лучше заранее проверять некоторые условия и избегать вызова / выполнения задачи, которая может привести к исключению. НО, если вы начнете проверять каждую вещь, у вас будет огромный кусок кода, выполняющий только различные проверки, которые могут быть очень трудными для сопровождения / чтения. Если есть какой-то «правильный» способ справиться с подобными делами, даже я бы хотел знать :-)
Теги:
exception

3 ответа

0

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

НЕТ, совсем нет, и это точно известно как Abusing Exception Handling. Когда вы уже знаете, что что-то может пойти не так, что можно исправить или проверить; то почему бы не сделать эту проверку сначала, а обернуть ее вокруг try.. catch.

Например, вы можете сделать следующее

Console.WriteLine("Please enter a number");
try
{
int num = Convert.ToInt32(Console.ReadLine());
}
//if someone enter a 'string' in place of Integer, it will cause
catch(InvalidFormatException ix) 
{
}
catch(Exception ex)
{
}

Это можно легко избежать, выполнив проверку и используя TryParse() например

Console.WriteLine("Please enter a number");
int num;
if (int.TryParse(Console.ReadLine(), out num))
 {

 }
else
 {
   Console.WriteLine("Not a valid integer number");
 }
0

Это зависит от того, есть ли у вас хороший способ справиться со случаем отсутствия элемента i или нет.

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

Некоторые примеры обработки

Возможно, вы захотите использовать значение по умолчанию, потому что, может быть, неважно, если там ничего нет, это обычный, ожидаемый и обработанный случай:

public Item GetItem(int i)
{
  if(list.Count>i)
    return list[i];
  else
    return null; //default value, could be an Item if that makes sense, see Null Object Pattern
}

Или вы можете захотеть создать более значимое настраиваемое исключение, если вам нужно его где-то поймать (но не используйте исключения для нормального потока программы, это должен быть исключительный случай):

public Item GetItem(int i)
{
  if(list.Count>i)
    return list[i];
  else
    throw new NoItemException();
}

Или вы можете просто задать более значимое сообщение об исключении, для вас или, может быть, для пользователя/поддержки:

public Item GetItem(int i)
{
  if(list.Count>i)
    return list[i];
  else
    throw new Exception("There was no element found in the list of X at " + i);
}
  • 0
    В вашем первом примере, как насчет просто сделать попытку catch и вернуть null для catch. List выполняет проверку границ и выдает исключение.
  • 0
    Вы могли бы, но я бы сделал это только в крайнем случае. Главным образом потому, что мне пришлось бы искать, какой тип исключения ловить, поскольку я не хотел бы ловить все.
0

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

Как определить, является ли случай исключительным? Это действительно сводится к предположениям вашего кода (который должен быть документирован).

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

Сравните это с тем, когда кто-то просит ваш код вернуть элемент со значением "Foo". Здесь не разумно, чтобы ваш код предположил, что такой элемент должен существовать (поскольку вызывающий сервер действительно запрашивает, не зная о вашей внутренней детали реализации, то есть индексы), и если элемент не найден, это не считается исключительным вообще, поэтому вместо того, чтобы бросать исключение, вы возвращаете null.

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню