---
# System prepended metadata

title: 分支
tags: [控制流]

---

# [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'));
```













