152 lines
3.1 KiB
Markdown
152 lines
3.1 KiB
Markdown
# Error Handling in Dart: A Comprehensive Guide
|
|||
|
|
|
||
|
|
Proper error handling is crucial for writing robust and reliable Dart applications. This guide covers the main concepts and techniques for handling errors in Dart.
|
||
|
|
|
||
|
|
## 1. Try-Catch Blocks
|
||
|
|
|
||
|
|
The try-catch block is the primary mechanism for handling exceptions in Dart.
|
||
|
|
|
||
|
|
### Example:
|
||
|
|
|
||
|
|
```dart
|
||
|
|
void main() {
|
||
|
|
try {
|
||
|
|
int result = 12 ~/ 0; // Integer division by zero
|
||
|
|
print(result);
|
||
|
|
} on IntegerDivisionByZeroException {
|
||
|
|
print('Cannot divide by zero');
|
||
|
|
} catch (e) {
|
||
|
|
print('An error occurred: $e');
|
||
|
|
} finally {
|
||
|
|
print('This always executes');
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
## 2. Throwing Exceptions
|
||
|
|
|
||
|
|
You can throw exceptions using the `throw` keyword.
|
||
|
|
|
||
|
|
### Example:
|
||
|
|
|
||
|
|
```dart
|
||
|
|
void validateAge(int age) {
|
||
|
|
if (age < 0) {
|
||
|
|
throw ArgumentError('Age cannot be negative');
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void main() {
|
||
|
|
try {
|
||
|
|
validateAge(-5);
|
||
|
|
} catch (e) {
|
||
|
|
print('Error: $e');
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
## 3. Custom Exceptions
|
||
|
|
|
||
|
|
You can create custom exception classes by extending `Exception` or `Error`.
|
||
|
|
|
||
|
|
### Example:
|
||
|
|
|
||
|
|
```dart
|
||
|
|
class InsufficientFundsException implements Exception {
|
||
|
|
final double balance;
|
||
|
|
final double withdrawal;
|
||
|
|
|
||
|
|
InsufficientFundsException(this.balance, this.withdrawal);
|
||
|
|
|
||
|
|
@override
|
||
|
|
String toString() => 'Insufficient funds: $balance available, $withdrawal requested';
|
||
|
|
}
|
||
|
|
|
||
|
|
void withdraw(double balance, double amount) {
|
||
|
|
if (amount > balance) {
|
||
|
|
throw InsufficientFundsException(balance, amount);
|
||
|
|
}
|
||
|
|
// Proceed with withdrawal
|
||
|
|
}
|
||
|
|
|
||
|
|
void main() {
|
||
|
|
try {
|
||
|
|
withdraw(100, 150);
|
||
|
|
} on InsufficientFundsException catch (e) {
|
||
|
|
print(e);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
## 4. Async Error Handling
|
||
|
|
|
||
|
|
When working with asynchronous code, you can use try-catch with async-await.
|
||
|
|
|
||
|
|
### Example:
|
||
|
|
|
||
|
|
```dart
|
||
|
|
Future<String> fetchData() async {
|
||
|
|
// Simulating network request
|
||
|
|
await Future.delayed(Duration(seconds: 2));
|
||
|
|
throw Exception('Failed to fetch data');
|
||
|
|
}
|
||
|
|
|
||
|
|
void main() async {
|
||
|
|
try {
|
||
|
|
String data = await fetchData();
|
||
|
|
print(data);
|
||
|
|
} catch (e) {
|
||
|
|
print('Error occurred: $e');
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
## 5. Error Propagation
|
||
|
|
|
||
|
|
You can rethrow exceptions to propagate them up the call stack.
|
||
|
|
|
||
|
|
### Example:
|
||
|
|
|
||
|
|
```dart
|
||
|
|
void processData(String data) {
|
||
|
|
try {
|
||
|
|
// Process data
|
||
|
|
throw FormatException('Invalid data format');
|
||
|
|
} catch (e) {
|
||
|
|
print('Error in processData: $e');
|
||
|
|
rethrow; // Rethrow the caught exception
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void main() {
|
||
|
|
try {
|
||
|
|
processData('some data');
|
||
|
|
} catch (e) {
|
||
|
|
print('Error in main: $e');
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
## 6. Using `assert`
|
||
|
|
|
||
|
|
The `assert` statement is used to check boolean conditions during development.
|
||
|
|
|
||
|
|
### Example:
|
||
|
|
|
||
|
|
```dart
|
||
|
|
void setVolume(int volume) {
|
||
|
|
assert(volume >= 0 && volume <= 100, 'Volume must be between 0 and 100');
|
||
|
|
// Set volume
|
||
|
|
}
|
||
|
|
|
||
|
|
void main() {
|
||
|
|
setVolume(50); // OK
|
||
|
|
setVolume(150); // AssertionError in debug mode
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
Note: Assertions are only enabled in debug mode and are ignored in production code.
|
||
|
|
|
||
|
|
## Conclusion
|
||
|
|
|
||
|
|
Effective error handling is essential for creating robust Dart applications. By using these techniques, you can gracefully handle exceptions, provide meaningful error messages, and improve the reliability of your code.
|