← Назад к вопросам

В чём разница между checked exception и unchecked exception?

2.3 Middle🔥 101 комментариев
#C# и ООП

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Разница между Checked и Unchecked Exception в C#

В контексте C# и .NET (на котором построен Unity) термины checked exception и unchecked exception имеют специфическое значение, отличное от Java. В C# эти понятия относятся не к типам исключений, а к арифметическому переполнению (overflow) при операциях с целочисленными типами данных. Это важный нюанс для разработки в Unity, где производительность и контроль над низкоуровневыми операциями (например, в циклах обновления, физике или процедурной генерации) могут быть критичны.

Checked Контекст (Проверяемое переполнение)

В checked контексте среда выполнения CLR проверяет, не приводит ли арифметическая операция с целыми числами (int, long, byte, short и т.д.) к переполнению за пределы допустимого диапазона типа. Если переполнение происходит, выбрасывается исключение System.OverflowException.

  • Этот контекст обеспечивает безопасность, но добавляет накладные расходы на проверку.
  • По умолчанию в C# проектах отключен (т.е. используется unchecked контекст) для повышения производительности, так как переполнение в большинстве сценариев считается редким.
  • Его можно включить глобально в настройках проекта или локально с помощью ключевого слова checked.
// Пример checked блока
int maxInt = int.MaxValue; // 2147483647

try
{
    checked
    {
        int overflow = maxInt + 1; // Эта строка выбросит OverflowException
        Debug.Log("Этот код не выполнится.");
    }
}
catch (OverflowException ex)
{
    Debug.LogError($"Произошло переполнение: {ex.Message}");
}

Unchecked Контекст (Непроверяемое переполнение)

В unchecked контексте (контекст по умолчанию) проверка на арифметическое переполнение не производится. Если результат операции выходит за границы типа, значение "обрезается" (переносится) согласно правилам двоичной арифметики.

  • Это поведение соответствует поведению процессора и является очень быстрым.
  • Может приводить к трудноуловимым багам, когда большое положительное число неожиданно становится отрицательным (или наоборот) без явного предупреждения.
  • Явно задаётся ключевым словом unchecked, но обычно используется по умолчанию.
// Пример unchecked контекста (поведение по умолчанию)
int maxInt = int.MaxValue;

unchecked // Необязательно, так как это контекст по умолчанию
{
    int result = maxInt + 1;
    Debug.Log($"Результат без проверки (переполнение): {result}"); // Выведет: -2147483648
}

Почему это важно в Unity Development?

  1. Производительность: В Update(), циклах обработки массивов данных или процедурной генерации, где тысячи целочисленных операций выполняются каждый кадр, unchecked контекст (по умолчанию) является оптимальным. Включение checked повсеместно может негативно сказаться на FPS.

  2. Безопасность и Отладка: При работе с критичными вычислениями, где целостность данных абсолютно важна (например, подсчёт игровой валюты, индексы для сохранений, генерация детерминированных seed), использование checked блоков помогает на этапе разработки и тестирования отловить потенциально опасные сценарии.

  3. Особые Кейсы: При компиляции в режиме IL2CPP для платформ, таких как iOS или WebGL, поведение по умолчанию может зависеть от настроек. Понимание этой разницы позволяет писать более переносимый и предсказуемый код.

Резюме и Рекомендации

КритерийChecked Exception (Контекст)Unchecked Exception (Контекст)
СутьПроверка арифметического переполнения с генерацией OverflowException.Отсутствие проверки. Переполнение приводит к переносу значения.
ПроизводительностьНиже (дополнительные проверки).Высокая (соответствует скорости процессора).
БезопасностьВысокая. Исключение сразу указывает на проблему.Низкая. Ошибки могут проявиться позже как логические.
Контекст по умолчанию в C#Нет.Да.
Явное указаниеКлючевое слово checked.Ключевое слово unchecked.

Практический совет для Unity-разработчика: Оставляйте контекст unchecked (по умолчанию) для всего проекта, чтобы не снижать производительность. Локально оборачивайте в checked блоки только те участки кода, где арифметическое переполнение действительно может стать серьёзной проблемой, и его нужно отловить на этапе разработки (например, расчёты в системе экономики или при работе с очень большими индексами). Используйте явные проверки (if (a > int.MaxValue - b)) в критически важной логике вместо глобального включения checked контекста.