# [Branches](https://dart.dev/language/branches)
* If
* If-case
* [Conditional expressions](https://dart.dev/language/operators#conditional-expressions)
* Switch statements
* [Switch expressions](https://www.christianfindlay.com/blog/dart-switch-expressions)
* Exhaustiveness checking 詳盡性檢查(就是要寫死)
* Guard clause
# [Exceptions](https://dart.dev/language/error-handling)
* Exception, Error, any not null obj
* throw, rethrow
* on xx catch e
* finally
* Assert
## if
```
String s = 'https://hackmd.io/';
if (s.startsWith('http')) {
print('it is a http url');
} else if (s.startsWith('ftp')) {
print("it's a ftp url");
} else {
print("it's not an url");
}
```
## If-case
if-case 語句提供了一種針對單一模式進行匹配和解構的方法。若要針對多種模式測試某個值,請使用switch, 匹配成功為真.
```
List<int> pair = [12, 23];
if (pair case [int x, int y]) {
print('Was coordinate array $x,$y');
} else {
throw FormatException('Invalid coordinates.');
}
```
## if 三元運算
```
int a = 5;
int b = 10;
// 使用三元运算符
String result = a > b ? 'a大于b' : 'a不大于b';
print(result);
// 使用 if 的简写形式
String message = if (a > b) 'a大于b' else 'a不大于b';
```
## if 運用在List
```
bool isLoggedIn = true;
List<String> menuItems = [
'首页',
'个人资料',
if (isLoggedIn) '退出登录' else '登录',
'设置'
];
print(menuItems); // [首页, 个人资料, 退出登录, 设置]
```
```
bool isLoggedIn = false;
List<String> menuItems = [
'首页',
'个人资料',
if (isLoggedIn) '退出登录' ,
'设置'
];
print(menuItems); // [首页, 个人资料, 设置]
```
## if 運用在Map
```
bool includeDetails = true;
var userInfo = {
'name': '张三',
'age': 25,
if (includeDetails) 'email': 'zhangsan@example.com',
if (includeDetails) 'phone': '123-456-7890'
};
print(userInfo);
// {name: 张三, age: 25, email: zhangsan@example.com, phone: 123-456-7890}
```
```
bool includeDetails = true;
var userInfo = {
'name': '张三',
'age': 25,
if (includeDetails) 'email': 'zhangsan@example.com' else 'phone':'0935859966'
};
print(userInfo);
```
## Conditional expressions
* condition?a:b
* a??b
```
var visibility = isPublic ? 'public' : 'private';
String playerName(String? name) => name ?? 'Guest'; // if-null operator
```
## Switch statements
當沒有case子句匹配時,使用default或通配符_執行程式碼
空的case被匹配到時, 會執行下一個case
```
int c = 12;
switch (c) {
case 12:
case 13:
print('13 or 12');
default:
print('not match');
}
// 印出 13 or 12
```
continue會直接執行label處的case然後停止
```
int number = 2;
switch (number) {
case 1:
print('Case 1');
case 2:
print('Case 2, falling through to case 3');
continue label; // Continue to case 3
case 3:
print('Case 3');
label:
case 4:
print('Case 4');
default:
print('Default case');
}
```
```
List<int> numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
for (int number in numbers) {
switch (number) {
case 3:
case 4:
print('Skipping $number');
continue; // Skip the rest of this iteration
case 6:
print('Special case for $number');
break; // Exit the switch and continue the loop
default:
print('Processing $number');
}
}
```
## Switch expressions
能夠使用expression的地方都可以使用
```
var x = switch (y) { ... };
print(switch (x) { ... });
return switch (x) { ... };
```
```
// Where slash, star, comma, semicolon, etc., are constant variables...
token = switch (charCode) {
slash || star || plus || minus => operator(charCode),
comma || semicolon => punctuation(charCode),
>= digit0 && <= digit9 => number(),
_ => throw FormatException('Invalid')
};
```
## Exhaustiveness checking
就是比對值進入switch後一定要有比對到, 否則報錯
ex. 如果有人新增Shape的子類型, 則switch expression會檢查出來
```
import 'dart:math';
sealed class Shape {}
class Square implements Shape {
final double length;
Square(this.length);
}
class Circle implements Shape {
final double radius;
Circle(this.radius);
}
double calculateArea(Shape shape) => switch (shape) {
Square(length: var l) => l * l,
Circle(radius: var r) => pi * r * r
};
void main() {
Shape c = Circle(5);
print(calculateArea((c)));
}
```
## Guard clause
就是多增加限制條件, if-case或switch statement或expression都可以有,當保護子句的計算結果為 false 時,將繼續執行下一個 case,而不是退出switch
```
class Person {
String name;
int age;
int yearExoerience;
Person(this.name, this.age, this.yearExoerience);
}
void main() {
List stuff = [
Person('John', 23, 3),
Person('Mary', 29, 2),
Person('Bob', 35, 4),
123,
456,
true
];
for (var p in stuff) {
switch (p) {
case Person(name: var n, age: var a, yearExoerience: var y)
when a <= 30 && a > 20:
print('${n} is young, his yearExoerience is $y');
break;
case Person(name: var n, age: var a, yearExoerience: var y) when a > 30:
print('$n is over 30 yo.');
}
}
print('----------------');
for (var p in stuff) {
String ret = switch (p) {
Person(name: var n, age: var a, yearExoerience: var y)
when a <= 30 && a > 20 =>
"${n} is young, his yearExoerience is $y",
Person(name: var n, age: var a, yearExoerience: var y) when a > 30 =>
'$n is over 30 yo.',
_ => ''
};
print(ret);
}
}
```
## [Exceptions](https://dart.dev/language/error-handling)
Dart 提供了[Exception](https://api.dart.dev/stable/3.5.1/dart-core/Exception-class.html)和[Error](https://api.dart.dev/stable/3.5.1/dart-core/Error-class.html)類型,以及其預先定義的子類型。Dart 程式可以拋出任何非 null 物件作為異常。
```
throw FormatException('Expected at least 1 section');
// 拋出任意非null物件
throw 'Out of llamas!';
// throw 是個expression
void distanceTo(Point other) => throw UnimplementedError();
```
catch綜合範例
```
try {
// ···
} on FormatException {
// 捕捉指定的異常
} on Exception catch (e) {
// 捕捉所有Exception類
print('Exception details:\n $e')
} catch (e) {
// 捕捉所有非null異常物件
print('Something really unknown: $e');
} catch (e, s) {
// s 是堆疊追蹤
print('Exception details:\n $e');
print('Stack trace:\n $s');
} finally {
// 一定會執行
}
```
rethrow 希望異常繼續傳播
```
void misbehave() {
try {
dynamic foo = true;
print(foo++); // Runtime error
} catch (e) {
// 初步處理異常
print('misbehave() partially handled ${e.runtimeType}.');
// 讓main()也取得異常
rethrow;
}
}
void main() {
try {
misbehave();
} catch (e) {
print('main() finished handling ${e.runtimeType}.');
}
}
```
Assert
` assert(<condition>, <optionalMessage>);`
condition==false時會中斷程式執行
```
assert(text != null);
assert(number < 100,'$number is bigger than 100');
assert(urlString.startsWith('https'));
```