Ответ 1
Поскольку этот вопрос отмечен как "С#", мы можем ссылаться на Руководство по разработке .NET Framework как хорошую отправную точку для ответа на эти типы вопросов. Это руководство, приведенное в MSDN под "Бросок исключений" :
Не используйте исключения для нормального потока управления, если это возможно. Кроме для сбоев системы и операций с потенциальными условиями гонки, дизайнеры рамок должны проектировать API, чтобы пользователи могли писать код что не вызывает исключений. Например, вы можете предоставить способ проверьте предварительные условия перед вызовом участника, чтобы пользователи могли писать код, который не генерирует исключений.
Вот пример практики bad, где обрабатывается исключение, но почти всегда можно избежать:
public int? GetItem(int index)
{
int? value = null;
try
{
value = this.array[index];
}
catch (IndexOutOfRangeException)
{
}
return value;
}
Это кажется надуманным, но я часто вижу такой код от более новых программистов. Предполагая правильную синхронизацию при чтении и записи на array
, это исключение можно устранить на 100%. Учитывая, что лучший способ написать этот код будет следующим:
public int? GetItem(int index)
{
int? value = null;
// Ensure the index is within range in the first place!
if (index >= 0 && index < this.array.Length)
{
value = this.array[index];
}
return value;
}
Существуют и другие случаи, когда вы не можете разумно избегать исключений и просто должны их обрабатывать. Это чаще всего встречается, когда вам приходится иметь дело с внешними ресурсами, такими как файлы или сетевые соединения, с которыми вы могли бы в любой момент потерять доступ или связаться с ними. Пример из WCF:
public void Close()
{
// Attempt to avoid exception by doing initial state check
if (this.channel.State == CommunicationState.Opened)
{
try
{
// Now we must do a (potentially) remote call;
// this could always throw.
this.channel.Close();
}
catch (CommunicationException)
{
}
catch (TimeoutException)
{
}
}
// If Close failed, we might need to do final cleanup here.
if (this.channel.State == CommunicationState.Faulted)
{
// local cleanup -- never throws (aside from catastrophic situations)
this.channel.Abort();
}
}
Даже в приведенном выше примере хорошо проверить, что операция, которую вы собираетесь делать, по крайней мере, имеет шанс преуспеть. Таким образом, по-прежнему существует проверка if ()
, за которой следует соответствующая логика обработки исключений.