Learn to handle errors gracefully and build robust apps
Exceptions are errors that occur during program execution. They can be caused by:
Error handling allows your program to:
`Exception
├── IOException
├── FormatException
├── ArgumentError
├── StateError
└── ... (many more)
`The try-catch statement catches exceptions when they occur.
``dartry {
// Code that might throw an exception
riskyOperation();
} catch (error) {
// Handle the error
print('Caught error: $error');
} finally {
// Code that always runs (optional)
cleanup();
}
`**try**: Contains risky code that might throw an exception
**catch**: Handles specific exception types
**finally**: Runs whether exception occurs or not
You can catch different exception types with separate blocks.
``dartry {
riskyOperation();
} on FormatException catch (e) {
print('Format error: $e');
} on ArgumentError catch (e) {
print('Argument error: $e');
} catch (e) {
print('Unknown error: $e');
}
`**Best Practice**: Be specific with 'on', use 'catch' as fallback
Throw exceptions to signal errors.
``darvoid validateAge(int age) {
if (age < 0) {
throw ArgumentError('Age cannot be negative');
}
if (age > 150) {
throw RangeError('Age seems too high');
}
}
`Create your own exception classes for specific situations.
``darclass InsufficientFundsException implements Exception {
String message = '';
InsufficientFundsException(this.message);
@override
String toString() => message;
}
void withdraw(double amount, double balance) {
if (amount > balance) {
throw InsufficientFundsException(
'Withdrawal of $amount exceeds balance of $balance'
);
}
}
`1. **Be Specific**: Catch specific exceptions, not all
2. **Clean Up Resources**: Use finally for cleanup
3. **Log Errors**: Record what went wrong
4. **Provide Context**: Include relevant information in messages
5. **Don't Ignore Errors**: Always handle or propagate
6. **Fail Fast**: Detect errors early
7. **Test Error Cases**: Write tests for error scenarios