TGViewer
.NET Разработчик .NET Разработчик @netdeveloperdiary · 6.75K subscribers
Post #293 578
День двести пятьдесят третий. #ЗаметкиНаПолях
Фильтры исключений
Представьте, что вы выполняете веб-операцию и знаете, что сервер, к которому вы подключаетесь, иногда недоступен. Если вам не удаётся подключиться к нему, то у вас есть запасной вариант, однако любой другой вид сбоя должен привести к обычному выбросу исключения. До C #6 нужно было поймать исключение и выбросить его повторно, если статус отличался от нужного:
try {…}
catch (WebException e)
{
if (e.Status != WebExceptionStatus.ConnectFailure)
{
throw;
}
…
}

Используя фильтры исключений, если вы не хотите обрабатывать исключение, можно не перехватывать его, а отфильтровать сразу в блоке catch:
try {…}
catch (WebException e)
when (e.Status == WebExceptionStatus.ConnectFailure) {…}


Варианты использования:
1. Перехват одного исключения несколько раз
В прошлом всегда было ошибкой указывать один и тот же тип исключения в нескольких блоках catch для одного и того же блока try. Это не имело смысла, потому что второй блок никогда не достигался. С фильтрами исключений ситуация изменилась. Предположим, вы извлекаете веб-контент на основе URL-адреса, предоставленного пользователем. Возможно, вы захотите обработать сбой соединения одним способом, сбой разрешения домена другим способом и не обрабатывать другие типы сбоев:
try {…}
catch (WebException e)
when (e.Status == WebExceptionStatus.ConnectFailure) {…}
catch (WebException e)
when (e.Status == WebExceptionStatus.NameResolutionFailure) {…}

Если вы хотите обработать все другие исключения WebException на том же уровне, можно добавить общий блок catch (WebException e) {…} без фильтра последним пунктом.

2. Повторные попытки
Облачные вычисления становятся все более распространенными, и мы, как правило, всё больше узнаём об операциях, которые могут привести к сбою, и о задумываемся о том, как обрабатывать сбои в нашем коде. При удаленных операциях - например, вызовах удалённых веб-служб и баз данных - иногда возникают временные сбои, и можно безопасно повторить попытку. Вот как это можно реализовать, используя фильтры исключений:
static T Retry<T>(Func<T> operation, int attempts)
{
while (true)
{
try
{
attempts--;
return operation();
}
catch (Exception e) when (attempts > 0)
{
Console.WriteLine($"Неудача: {e}");
Console.WriteLine($"Осталось попыток: {attempts}");
Thread.Sleep(5000);
}
}
}


3. Запись в лог, как побочный эффект
Иногда полезно записывать исключение в лог, даже если оно будет перехвачено на более верхних уровнях. Вы можете использовать для этого фильтры исключений, чтобы не нарушать поток выполнения. Всё, что вам нужно, это фильтр исключений, который вызывает метод для записи в лог и возвращает false, чтобы указать, что вы не хотите перехватывать это исключение:
try {…}
catch (Exception e) when (Log(e)) {…}
…
static bool Log(Exception e)
{
Console.WriteLine($"{DateTime.UtcNow}: {e.GetType()} {e.Message}");
return false;
}

Источник: Jon Skeet “C# In Depth”. 4th ed – Manning Publications Co, 2019. Глава 10.
  • 👍 1
More from @netdeveloperdiary
  1. Sep 29, 2026Фото 3 (с) Анатолий Кулаков
  2. Sep 29, 2026День 2799. Конференция DotNext 2026. Часть 1 25 и 26 сентября в Москве прошла очередная ко…
  3. Sep 28, 2026День 2798. #Оффтоп Утиная Типизация в C# с Помощью Перехватчиков. Часть 2 Некоторое время…
  4. Sep 27, 2026День 2797. #ЗаметкиНаПолях #AI Рабочий процесс с Copilot для .NET. Окончание Начало Продол…
  5. Sep 26, 2026День 2796. #ЗаметкиНаПолях #AI Рабочий процесс с Copilot для .NET. Продолжение Начало Три…
  6. Sep 25, 2026День 2795. #ЗаметкиНаПолях #AI Рабочий процесс с Copilot для .NET. Начало Проблема с позиц…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →