Обработка исключений в C#: try, catch, finally, throw и лучшие практики
Что такое исключение
Исключение (exception) — ошибка времени выполнения, нарушающая нормальный поток программы. В C# исключения — объекты, наследуемые от System.Exception. Обработка построена на четырёх ключевых словах: try, catch, finally, throw.
Синтаксис try-catch-finally
try
{
// код, который может выбросить исключение
}
catch (ExceptionType1 ex)
{
// обработка конкретного типа
}
catch (ExceptionType2 ex)
{
// обработка другого типа
}
catch (Exception ex) // базовый catch — в конце
{
// обработка остальных
}
finally
{
// выполняется ВСЕГДА (даже при return в try/catch)
// очистка ресурсов: закрытие файлов, соединений
}
Пример: деление на ноль
using System;
public class DivNumbers
{
public void Divide(int a, int b)
{
try
{
int result = a / b;
Console.WriteLine($"Result: {result}");
}
catch (DivideByZeroException ex)
{
Console.WriteLine($"Ошибка: {ex.Message}");
}
finally
{
Console.WriteLine("Операция завершена");
}
}
}
// Divide(10, 0) → "Ошибка: Attempted to divide by zero." + "Операция завершена"
Иерархия исключений
System.Object
└─ System.Exception
├─ System.ApplicationException (базовый для пользовательских)
└─ System.SystemException (базовый для системных)
├─ ArgumentException
│ ├─ ArgumentNullException
│ └─ ArgumentOutOfRangeException
├─ InvalidOperationException
├─ NullReferenceException
├─ IndexOutOfRangeException
├─ DivideByZeroException
├─ InvalidCastException
├─ IOException
│ ├─ FileNotFoundException
│ └─ DirectoryNotFoundException
├─ OutOfMemoryException
└─ StackOverflowException
Пользовательские исключения
[Serializable]
public class TemperatureException : Exception
{
public double Temperature { get; }
public TemperatureException(string message, double temp)
: base(message)
{
Temperature = temp;
}
// Для сериализации (optional в .NET Core)
protected TemperatureException(SerializationInfo info, StreamingContext context)
: base(info, context)
{
Temperature = info.GetDouble("Temperature");
}
public override void GetObjectData(SerializationInfo info, StreamingContext context)
{
base.GetObjectData(info, context);
info.AddValue("Temperature", Temperature);
}
}
// Использование
public class Thermometer
{
public void Check(double temp)
{
if (temp < -273.15)
throw new TemperatureException("Below absolute zero!", temp);
}
}
Throw — выбрасывание исключений
// 1. Новое исключение
throw new ArgumentNullException(nameof(param), "Parameter cannot be null");
// 2. Повторное выброс (сохраняет stack trace)
catch (Exception ex)
{
Log(ex);
throw; // НЕ "throw ex" — он сбрасывает stack trace!
}
// 3. Обёртывание (wrapping)
catch (SqlException ex)
{
throw new DataAccessException("Database error", ex); // InnerException
}
Идиома using / IDisposable (рекомендуется вместо finally для ресурсов)
// Файл автоматически закроется даже при исключении
using (var file = File.OpenRead("data.txt"))
{
// работа с файлом
}
// C# 8: using declaration
using var file = File.OpenRead("data.txt");
// файл закроется в конце области видимости переменной
Exception Filters (C# 6.0+)
Условие для catch-блока:
try { ... }
catch (HttpException ex) when (ex.StatusCode == 404)
{
// только 404
}
catch (HttpException ex) when (ex.StatusCode >= 500)
{
// серверные ошибки
}
catch (HttpException ex)
{
// остальные HTTP ошибки
}
Лучшие практики
- Ловите конкретные типы исключений, а не просто
Exception - Не подавляйте исключения пустым
catch { }— минимум логируйте - Используйте
throw;(неthrow ex;) для повторного выброса - Используйте
using/IDisposableдля ресурсов вместоfinally - Не используйте исключения для управления потоком (flow control) — это медленно
- Пользовательские исключения: наследовать от
Exception(неApplicationException— устарел), суффиксException, сериализуемы - Документируйте исключения в XML-комментариях:
<exception cref="ArgumentNullException">...</exception>
Язык C
- Освоение операторов using в C#: импорт, псевдонимы и статические директивы
- Работа с файлами в C: мастерство ввода-вывода с fopen, fprintf, fread и fseek
- Обработка исключений в Python: try, except, else и finally подробно
- Обработка исключений в Java: try, catch, finally, throw и throws
- Обработка исключений в C++: практические примеры try, catch, throw
- Мастерство обработки исключений в Python: эффективное использование try, except, finally и raise
- Освоение обработки сигналов в C++: безопасное управление прерываниями и корректное завершение программы
- Java 9 Module System: модули, link-time и кастомные runtime-образы
- PLC vs DCS: выбор правильной системы автоматизации
- Liebherr PHS Allround: гибкая модульная паллетная система для высокопроизводительного производства