В чем разница между Error и Exception в Dart?

Ответ

В Dart и Error, и Exception представляют собой объекты, которые могут быть "выброшены" (throw), но они несут разную семантическую нагрузку, следуя соглашениям языка.

  • Exception — предназначен для ожидаемых проблем в логике работы программы, которые разработчик должен предусмотреть и обработать. Это сбои в бизнес-логике, вводе данных, сетевых запросах.

    • Примеры: FormatException, TimeoutException, SocketException.
    • Создавайте свои исключения, наследуясь от Exception.
      
      class ValidationException implements Exception {
      final String message;
      ValidationException(this.message);
      @override
      String toString() => 'ValidationException: $message';
      }

    // Использование void processEmail(String email) { if (!email.contains('@')) { throw ValidationException('Invalid email format'); } // ... }

  • Error — представляет критические сбои в самой программе или виртуальной машине, которые обычно указывают на ошибку в коде или невосстановимые состояния среды выполнения. Их, как правило, не следует ловить.

    • Примеры: OutOfMemoryError, StackOverflowError, NoSuchMethodError.
    • Создавать собственные классы Error стоит только для обозначения действительно фатальных условий в программе или библиотеке.

Обработка на практике:

try {
  var data = await fetchDataFromNetwork();
  var number = int.parse(data['value']); // Может выбросить FormatException
} on SocketException catch (e) {
  // Обрабатываем конкретное исключение (нет сети)
  showOfflineSnackBar();
} on FormatException catch (e) {
  // Обрабатываем другое конкретное исключение
  log('Data format error: $e');
} catch (e, s) {
  // Универсальный catch для всего остального (включая Error, что нежелательно)
  log('Unexpected error: $enStack: $s', level: Level.error);
  rethrow; // Часто лучше дать упасть и залогировать на верхнем уровне
} finally {
  // Код, который выполнится в любом случае (например, закрытие ресурсов)
  cleanup();
}

Основное правило: ловите и обрабатывайте Exception, а Error позволяйте всплывать, чтобы они были залогированы и исправлены на этапе разработки.

Ответ 18+ 🔞

А, ну вот, опять про эти ваши Exception и Error в Dart. Сидишь такой, пишешь код, и тут — ёпта — бац, и всё накрылось медным тазом. Так вот, чтобы не охуеть с непривычки, давай разберемся, кто есть ху.

В общем, и Error, и Exception — это такие объекты, которые можно выкинуть на голову (throw), но несут они, блядь, совершенно разный посыл. Это как сравнивать «ой, я чашку уронил» и «ой, у меня дом горит». Одно — бытовуха, другое — пиздец.

Exception — это для ожидаемых косяков в логике. Типа, пользователь ввёл ерунду вместо почты, сеть легла, таймаут случился. Всё это — штатные ситуации, которые ты, как не лох, должен предвидеть и обработать. Это типа FormatException, TimeoutException. Свои косяки тоже делаешь, наследуясь от Exception.

class MyStupidUserException implements Exception {
  final String message;
  MyStupidUserException(this.message);
  @override
  String toString() => 'MyStupidUserException: $message'; // "Чё ввёл, долбоёб?"
}

void validatePassword(String pass) {
  if (pass.length < 8) {
    throw MyStupidUserException('Пароль — не "123", мудила!');
  }
}

Error — это уже пиздопроебибна. Это не ошибка логики, а пиздец в самой программе или в виртуальной машине. Память кончилась (OutOfMemoryError), стек переполнился, метод не найден. Это — красная кнопка, ядрёна вошь. Такое ловить — последнее дело, это знак, что код — говно, и надо чинить, а не прятать.

Как на практике выглядит обработка? Вот смотри, чувак:

try {
  var data = await fetchDataFromNetwork(); // Может сеть сдохнуть
  var number = int.parse(data['value']); // А тут пользователь-кретин может хуйню вписать
} on SocketException catch (e) {
  // Ловим конкретно "сеть отвалилась"
  showOfflineSnackBar(); // Говорим: "Иди отсюда, нет интернета"
} on FormatException catch (e) {
  // Ловим "пользователь — рукожоп"
  log('Ну что за данные, блядь: $e');
} catch (e, s) {
  // А это — универсальная помойка. Сюда может прилететь ВСЁ, даже `Error`.
  // Но ловить `Error` — идея так себе, доверия ебать ноль.
  log('Охуеть не встать, что это было: $enСтек: $s', level: Level.error);
  rethrow; // Чаще всего лучше дать всему ебануться дальше и залогировать на высшем уровне
} finally {
  // А это выполнится ВСЕГДА. Закрыть файл, отпустить соединение — дело такое.
  cleanup();
}

Короче, правило простое, как хуй с горы: лови и обрабатывай Exception (штатные косяки), а Error (критический пиздец) — не трогай, пусть летит наверх, чтобы ты увидел, охренел и пофиксил свой кривой код. Всё.