Пользовательские исключения и проектирование ошибок
Создавайте небольшие пользовательские исключения, выбирайте подходящие встроенные типы (ArgumentException, InvalidOperationException) и добавляйте контекст с помощью InnerException.
«Пользовательские исключения и проектирование ошибок» — бесплатный урок C# Academy на CoddyKit. Это урок 2 из 3. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения C# Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс C# Academy содержит 3 уроков всего.
Назначение и цели
Цель: сделать ошибки понятными и доступными для перехвата.
- Использовать конкретный тип для конкретной причины сбоя
- Добавлять хорошее сообщение и InnerException для контекста
- Отдавать предпочтение встроенным типам, когда они подходят
Пользовательский тип исключения
Наследуйте тип от Exception, заканчивайте его имя суффиксом Exception и добавьте стандартные конструкторы. Храните небольшие полезные данные.
using System;
// Custom, specific to our domain
public sealed class ConfigNotFoundException : Exception
{
public string Key { get; private set; }
public ConfigNotFoundException(string key)
: base("Config key not found: " + key)
{
Key = key;
}
public ConfigNotFoundException(string key, Exception inner)
: base("Config key not found: " + key, inner)
{
Key = key;
}
}
public class Program
{
public static void Main(string[] args)
{
try
{
throw new ConfigNotFoundException("ApiUrl");
}
catch (ConfigNotFoundException ex)
{
Console.WriteLine(ex.Message);
}
}
}
InnerException для контекста
Оборачивайте исключения нижнего уровня в доменное исключение и устанавливайте InnerException, чтобы сохранить корневую причину.
using System;
using System.IO;
public sealed class ConfigNotFoundException : Exception
{
public string Key { get; private set; }
public ConfigNotFoundException(string key, Exception inner)
: base("Config key not found: " + key, inner) { Key = key; }
}
public static class Config
{
public static string Load(string path, string key)
{
try
{
string[] lines = File.ReadAllLines(path); // may throw
for (int i = 0; i < lines.Length; i++)
{
int idx = lines[i].IndexOf("=");
if (idx > 0 && lines[i].Substring(0, idx) == key)
return lines[i].Substring(idx + 1);
}
throw new ConfigNotFoundException(key, null);
}
catch (IOException io)
{
// Wrap low-level error with domain meaning
throw new ConfigNotFoundException(key, io);
}
}
}
public class Program
{
public static void Main(string[] args)
{
try
{
Console.WriteLine(Config.Load("missing.cfg", "ApiUrl"));
}
catch (ConfigNotFoundException ex)
{
Console.WriteLine("Top: " + ex.Message);
if (ex.InnerException != null)
Console.WriteLine("Inner: " + ex.InnerException.GetType().Name);
}
}
}
Сначала выбирайте встроенные типы
Используйте встроенные типы для распространённых проблем: ArgumentNullException, ArgumentOutOfRangeException, FormatException, InvalidOperationException и т. д.
using System;
public static class MathUtil
{
public static int Divide(int a, int b)
{
if (b == 0) throw new DivideByZeroException();
return a / b;
}
public static int ParsePositive(string text)
{
if (text == null) throw new ArgumentNullException("text");
int value = int.Parse(text); // may throw FormatException
if (value <= 0) throw new ArgumentOutOfRangeException("text", "must be > 0");
return value;
}
}
public class Program
{
public static void Main(string[] args)
{
try { Console.WriteLine(MathUtil.ParsePositive("-1")); }
catch (ArgumentOutOfRangeException ex) { Console.WriteLine("Range: " + ex.ParamName); }
}
}
Исключения и защитные проверки
Используйте исключения для исключительных ситуаций. Для ожидаемых сбоев отдавайте предпочтение защитным проверкам TryX или кодам возврата.
using System;
public static class Parser
{
// BAD: using exceptions for expected cases
public static int ParseOrThrow(string s)
{
return int.Parse(s); // will throw often for user input
}
// GOOD: guard-check pattern for expected failure
public static bool TryParsePositive(string s, out int value)
{
value = 0;
int tmp;
if (!int.TryParse(s, out tmp)) return false;
if (tmp <= 0) return false;
value = tmp;
return true;
}
}
public class Program
{
public static void Main(string[] args)
{
int v;
if (Parser.TryParsePositive("12", out v))
Console.WriteLine("OK " + v);
else
Console.WriteLine("Invalid");
}
}
Контрольный список проектирования ошибок
Контрольный список:
- По возможности выбирайте встроенный тип.
- В противном случае создавайте небольшое CustomException со стандартными конструкторами.
- Добавляйте InnerException, чтобы сохранить корневую причину.
- Используйте исключения для непредвиденных случаев, а TryX — для ожидаемых сбоев.
Проектирование пользовательских исключений
Повторение
Повторение: отдавайте предпочтение встроенным исключениям; в противном случае определите небольшой пользовательский тип со стандартными конструкторами и используйте InnerException, чтобы добавить контекст, не теряя причину ошибки.
Часто задаваемые вопросы
Урок «Пользовательские исключения и проектирование ошибок» бесплатный?
Да — полный текст урока «Пользовательские исключения и проектирование ошибок» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс C# Academy, подпишись на CoddyKit PRO. Курс C# Academy содержит 3 уроков всего.
Чему я научусь в уроке «Пользовательские исключения и проектирование ошибок»?
Создавайте небольшие пользовательские исключения, выбирайте подходящие встроенные типы (ArgumentException, InvalidOperationException) и добавляйте контекст с помощью InnerException. Ты практикуешь C# Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать C# Academy?
Предыдущий опыт не требуется. C# Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 2 из 3.
Сколько времени занимает урок «Пользовательские исключения и проектирование ошибок»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке C# Academy?
Да. Каждый урок C# Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- try/catch/finally, создание исключения и повторный выброс
- Пользовательские исключения и проектирование ошибок
- IDisposable и оператор using