Exception Handling in Dart

Exception Handling in Dart#

Overview#

Exception handling in Dart is a crucial mechanism for managing errors and exceptional conditions that occur during program execution. It enables your application to handle errors gracefully, maintain stability, and provide meaningful feedback, preventing the program from crashing.

Basic Exception Handling: try, catch#

How It Works#

  • try: Encloses the code that might throw an exception.
  • catch: Handles exceptions thrown by the try block. You can specify different types of exceptions to handle or catch a general exception.
  • on: Offers a more specific way to catch exceptions of a particular type.

Example#

void main() {
  try {
    int result = 10 ~/ 0; // Division by zero
  } on IntegerDivisionByZeroException {
    print('Cannot divide by zero');
  } catch (e) {
    print('An error occurred: $e');
  } finally {
    print('This will always execute');
  }
}

In this example:

  • try block contains the code that may throw an exception.
  • on catches the specific IntegerDivisionByZeroException.
  • catch handles any other type of exception.
  • finally executes regardless of whether an exception occurred.

Throwing Exceptions: Using throw#

How It Works#

  • throw: Used to explicitly raise an exception when a specific condition or error occurs. You can throw built-in or custom exceptions.

Example#

void validateAge(int age) {
  if (age < 0) {
    throw ArgumentError('Age cannot be negative');
  }
}

void main() {
  try {
    validateAge(-5);
  } catch (e) {
    print('Caught an exception: $e');
  }
}

Here, throw raises an ArgumentError when the age is negative, and the catch block handles it.

Try-Catch-Finally: Ensuring Code Execution After Exceptions#

How It Works#

try: Contains code that might throw an exception.

  • catch: Handles any exceptions thrown by the try block.
  • finally: Executes code that should run regardless of whether an exception was thrown, typically used for cleanup operations.

Example#

void main() {
  try {
    int result = 10 ~/ 2; // Division by a valid number
    print('Result is $result');
  } catch (e) {
    print('An error occurred: $e');
  } finally {
    print('Cleanup operations');
  }
}

In this example:

  • try executes code that is likely to succeed.
  • catch handles potential exceptions.
  • finally runs cleanup code that needs to execute regardless of success or failure.

Custom Exceptions: Creating and Using Custom Exception Classes#

How It Works#

  • Custom Exception Classes: Define your own exception classes by extending the base Exception class or implementing the Exception interface.

Example#

class CustomException implements Exception {
  final String message;
  CustomException(this.message);
  
  @override
  String toString() => 'CustomException: $message';
}

void main() {
  try {
    throw CustomException('This is a custom exception');
  } catch (e) {
    print(e);
  }
}

Here, CustomException is a user-defined exception class that provides a custom error message.

Error Handling Best Practices: Effective Strategies for Managing Errors#

Best Practices#

  • Be Specific with Exceptions: Catch specific exceptions rather than using a generic catch-all.
  • Avoid Silent Failures: Ensure exceptions are logged or reported rather than ignored.
  • Use Custom Exceptions: Define custom exceptions for specific error scenarios to provide more meaningful error messages.
  • Validate Inputs: Preemptively validate inputs to prevent exceptions from occurring.
  • Cleanup Resources: Use finally to close resources or perform cleanup, ensuring it happens regardless of success or failure.

Example#

void processFile(String path) {
  try {
    if (path.isEmpty) {
      throw ArgumentError('File path cannot be empty');
    }
    // Simulate file processing
  } catch (e) {
    print('Error: $e');
  } finally {
    print('Finished processing');
  }
}
  • This example illustrates validating inputs and using finally to ensure cleanup occurs.

Overall#

Exception handling in Dart is essential for managing errors and maintaining program stability. By utilizing try, catch, finally, and custom exceptions, you can handle errors effectively and ensure your application remains robust and reliable.