目次

分岐

このページでは、分岐を使用してDartコードの制御フローを制御する方法を示します。

  • if文と要素
  • if-case文と要素
  • switch文と式

Dartでは、次を使用して制御フローを操作することもできます。

if

#

Dartは、オプションのelse句付きのif文をサポートしています。ifの後の括弧内の条件は、ブール値に評価される式である必要があります。

dart
if (isRaining()) {
  you.bringRainCoat();
} else if (isSnowing()) {
  you.wearJacket();
} else {
  car.putTopDown();
}

式コンテキストでifを使用する方法については、条件式を参照してください。

if-case

#

Dartのif文は、パターンに続くcase句をサポートしています。

dart
if (pair case [int x, int y]) return Point(x, y);

パターンが値と一致する場合、パターンがスコープ内に定義した変数を使用して分岐が実行されます。

前の例では、リストパターン[int x, int y]は値pairと一致するため、return Point(x, y)分岐はパターンが定義した変数xyを使用して実行されます。

そうでない場合、制御フローは、存在する場合はelse分岐に進み、実行されます。

dart
if (pair case [int x, int y]) {
  print('Was coordinate array $x,$y');
} else {
  throw FormatException('Invalid coordinates.');
}

if-case文は、単一のパターンに対して一致してデストラクチャリングを行う方法を提供します。複数のパターンに対して値をテストするには、switchを使用します。

switch文

#

switch文は、一連のケースに対して値式を評価します。各case句は、値が照合されるパターンです。あらゆる種類のパターンをケースに使用できます。

値がケースのパターンと一致すると、ケースの本体が実行されます。空でないcase句は、完了後にswitchの最後にジャンプします。break文は必要ありません。空でないcase句を終了する他の有効な方法は、continuethrow、またはreturn文です。

defaultまたはワイルドカード_句を使用して、case句と一致しない場合にコードを実行します。

dart
var command = 'OPEN';
switch (command) {
  case 'CLOSED':
    executeClosed();
  case 'PENDING':
    executePending();
  case 'APPROVED':
    executeApproved();
  case 'DENIED':
    executeDenied();
  case 'OPEN':
    executeOpen();
  default:
    executeUnknown();
}

空のケースは次のケースにフォールスルーするため、ケースが本体を共有できます。フォールスルーしない空のケースには、本体にbreakを使用します。非連続的なフォールスルーには、continue文とラベルを使用できます。

dart
switch (command) {
  case 'OPEN':
    executeOpen();
    continue newCase; // Continues executing at the newCase label.

  case 'DENIED': // Empty case falls through.
  case 'CLOSED':
    executeClosed(); // Runs for both DENIED and CLOSED,

  newCase:
  case 'PENDING':
    executeNowClosed(); // Runs for both OPEN and PENDING.
}

論理和パターンを使用して、ケースが本体またはガードを共有できるようにします。パターンとケース句の詳細については、switch文と式のパターンドキュメントを参照してください。

switch式

#

switchは、一致するケースの式本体に基づいて値を生成します。Dartで式が許可される場所であればどこでもswitch式を使用できますが、式文の開始時を除きます。例:

dart
var x = switch (y) { ... };

print(switch (x) { ... });

return switch (x) { ... };

式文の先頭にswitchを使用する場合は、switch文を使用してください。

switch式を使用すると、次のようなswitchを書き直すことができます。

dart
// Where slash, star, comma, semicolon, etc., are constant variables...
switch (charCode) {
  case slash || star || plus || minus: // Logical-or pattern
    token = operator(charCode);
  case comma || semicolon: // Logical-or pattern
    token = punctuation(charCode);
  case >= digit0 && <= digit9: // Relational and logical-and patterns
    token = number();
  default:
    throw FormatException('Invalid');
}

次のようなにします。

dart
token = switch (charCode) {
  slash || star || plus || minus => operator(charCode),
  comma || semicolon => punctuation(charCode),
  >= digit0 && <= digit9 => number(),
  _ => throw FormatException('Invalid')
};

switch式の構文は、switch文の構文とは異なります。

  • ケースはcaseキーワードで始まりません
  • ケース本体は、一連の文ではなく、単一の式です。
  • 各ケースには本体が必要です。空のケースには暗黙的なフォールスルーはありません。
  • ケースパターンは、:ではなく=>を使用して本体から区切られています。
  • ケースは,で区切られています(オプションで末尾の,も許可されます)。
  • デフォルトケースはdefault_の両方を使用する代わりに、_のみを使用できます。

網羅性チェック

#

網羅性チェックは、値がswitchに入力できるのにケースと一致しない可能性がある場合にコンパイル時エラーを報告する機能です。

dart
// Non-exhaustive switch on bool?, missing case to match null possibility:
switch (nullableBool) {
  case true:
    print('yes');
  case false:
    print('no');
}

デフォルトケース(defaultまたは_)は、switchを流れる可能性のあるすべての値をカバーします。これにより、あらゆる型のswitchが網羅的になります。

列挙型sealed型は、デフォルトケースがなくても可能な値が既知であり、完全に列挙できるため、switchに特に役立ちます。sealed修飾子をクラスで使用して、そのクラスのサブタイプを切り替える際の網羅性チェックを有効にします。

dart
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) => math.pi * r * r
    };

誰かがShapeの新しいサブクラスを追加した場合、このswitch式は不完全になります。網羅性チェックによって、欠落しているサブタイプが通知されます。これにより、多少関数型代数データ型スタイルでDartを使用できます。

ガード句

#

case句の後にオプションのガード句を設定するには、キーワードwhenを使用します。ガード句はif caseの後、およびswitch文と式の両方に続くことができます。

dart
// Switch statement:
switch (something) {
  case somePattern when some || boolean || expression:
    //             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Guard clause.
    body;
}

// Switch expression:
var value = switch (something) {
  somePattern when some || boolean || expression => body,
  //               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Guard clause.
}

// If-case statement:
if (something case somePattern when some || boolean || expression) {
  //                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Guard clause.
  body;
}

ガードは、一致したに任意のブール式を評価します。これにより、ケース本体を実行するかどうかについて、さらなる制約を追加できます。ガード句がfalseに評価されると、実行はswitch全体を終了するのではなく、次のケースに進みます。