ZetCode

Dart 表达式

最后修改日期:2025 年 6 月 4 日

表达式是 Dart 程序的核心,它们能够执行产生值的计算。本教程将探讨 Dart 表达式,详细介绍运算符类型、求值规则以及级联符号等独特功能。

Dart 表达式概述

在 Dart 中,表达式是求值为一个值的代码结构,例如字面量、变量、运算符或函数调用。Dart 提供了多种多样的运算符和表达式类型,为各种编程任务提供简洁且富有表现力的代码。

表达式类型 描述 Etitle="Dart 代码示例
字面量 直接的值表示 5, 'hello', true
算术 数学运算 a + b, x * y
关系 比较运算 a > b, x == y
逻辑运算 布尔运算 a && b, !flag
条件表达式 三元运算符 a ? b : c
级联符号 连续操作 obj..a()..b()
赋值 赋值 a = 5, b += 2

字面量表达式

字面量表达式直接在代码中表示固定值,支持 Dart 中的各种数据类型,包括整数(例如 42)、双精度浮点数(例如 3.14)、字符串(使用单引号、双引号或三引号)、布尔值(true、false)、列表、映射和 null 值。这些字面量提供了一种在程序中嵌入常量值的直接方式。

literals.dart
void main() {

  // Numeric literals
  int integer = 42;
  double floating = 3.14159;

  // String literals
  String singles = 'Single quotes';
  String doubles = "Double quotes";
  String multiline = '''
    Multi-line
    string
  ''';

  // Boolean literals
  bool truthy = true;
  bool falsy = false;

  // List and Map literals
  List<int> numbers = [1, 2, 3];
  Map<String, int> ages = {'Alice': 25, 'Bob': 30};

  print(integer);
  print(floating);
  print(singles);
  print(doubles);
  print(multiline);
  print(truthy);
  print(falsy);
  print(numbers);
  print(ages);
}

此示例展示了各种 Dart 字面量,演示了如何定义和打印整数、双精度浮点数、字符串(包括多行)、布尔值、列表和映射,突出了它们在代码中的直接用法。

$ dart run literals.dart
42
3.14159
Single quotes
Double quotes
    Multi-line
    string
  
[1, 2, 3]
{Alice: 25, Bob: 30}

算术表达式

Dart 支持通过加法 (+)、减法 (-)、乘法 (*)、除法 (/)、整数除法 (~/)、取模 (%) 和一元负号 (-) 等运算符进行标准的算术运算。除法运算符始终返回一个 double,而自增 (++) 和自减 (--) 运算符则修改值。这些运算符支持数学计算,包括混合类型运算。

arithmetic.dart
void main() {

  int a = 10;
  int b = 3;
  double c = 5.0;
  
  // Basic operations
  print('Addition: ${a + b}');
  print('Subtraction: ${a - b}');
  print('Multiplication: ${a * b}');
  print('Division: ${a / b}');
  print('Integer division: ${a ~/ b}');
  print('Modulo: ${a % b}');
  print('Unary minus: ${-a}');
  
  // Mixed type arithmetic
  print('Mixed addition: ${a + c}');
  
  // Increment/decrement
  int counter = 0;
  print('Post-increment: ${counter++}');
  print('After increment: $counter');
  print('Pre-decrement: ${--counter}');
}

此示例演示了算术运算,包括基本计算、混合类型加法以及自增/自减运算,说明了 Dart 如何处理数学表达式。

$ dart run arithmetic.dart
Addition: 13
Subtraction: 7
Multiplication: 30
Division: 3.3333333333333335
Integer division: 3
Modulo: 1
Unary minus: -10
Mixed addition: 15.0
Post-increment: 0
After increment: 1
Pre-decrement: 0

关系表达式和逻辑表达式

关系运算符,如等于 (==)、不等于 (!=)、大于 (>) 和小于 (<),会比较值以产生布尔结果。逻辑运算符,包括与 (&&)、或 (||) 和非 (!),用于组合布尔表达式。Dart 采用短路求值,跳过不必要的运算(例如,在 && 中,如果第一个操作数为 false),从而提高逻辑表达式的效率和安全性。

relational_logical.dart
void main() {

  int a = 5;
  int b = 10;
  
  // Relational operators
  print('Equal: ${a == b}');
  print('Not equal: ${a != b}');
  print('Greater than: ${a > b}');
  print('Less than: ${a < b}');
  print('Greater or equal: ${a >= b}');
  print('Less or equal: ${a <= b}');
  
  // Logical operators
  bool x = true;
  bool y = false;
  
  print('AND: ${x && y}');
  print('OR: ${x || y}');
  print('NOT: ${!x}');
  
  // Short-circuit evaluation
  String? name;
  bool isValid = name != null && name.isNotEmpty;
  print('Is valid: $isValid');
}

此示例说明了关系比较和逻辑运算,包括对可空字符串进行短路求值的演示,展示了 Dart 如何确保安全高效的表达式求值。

$ dart run relational_logical.dart
Equal: false
Not equal: true
Greater than: false
Less than: true
Greater or equal: false
Less or equal: true
AND: false
OR: true
NOT: false
Is valid: false

条件表达式

Dart 的条件表达式提供了简洁的决策制定结构。三元运算符 (?:) 充当紧凑的 if-else 语句,而空合并运算符 (??) 为 null 变量提供默认值。空感知运算符,如条件属性访问 (?.) 和空感知赋值 (??=),确保了可空类型的安全处理,使代码更加健壮和简洁。

conditional.dart
void main() {

  int age = 20;
  
  // Ternary operator
  String status = age >= 18 ? 'Adult' : 'Minor';
  print('Status: $status');
  
  // Null-coalescing operator
  String? name;
  String displayName = name ?? 'Guest';
  print('Welcome, $displayName');
  
  // Conditional property access
  List<int>? numbers;
  int? first = numbers?.first;
  print('First number: $first');
  
  // Null-aware assignment
  name ??= 'Anonymous';
  print('Name: $name');
}

此示例展示了条件表达式,包括用于基于年龄的状态的三元运算符、用于默认名称的空合并,以及用于安全列表访问和赋值的空感知运算符,展示了简洁的控制流。

$ dart run conditional.dart
Status: Adult
Welcome, Guest
First number: null
Name: Anonymous

级联符号

Dart 的级联符号 (..) 允许以流畅的方式对同一对象执行多个操作,并在每次操作后返回原始对象。此功能对于构建器样式的 API 尤其有用,它通过减少重复的对象引用来简化代码,提高了连续方法调用的可读性和可维护性。

cascade.dart
class Person {
  String name = '';
  int age = 0;
  
  void greet() => print('Hello, $name!');
  void birthday() => age++;
}

void main() {

  // Without cascade
  Person p1 = Person();
  p1.name = 'Alice';
  p1.age = 30;
  p1.greet();
  
  // With cascade
  Person p2 = Person()
    ..name = 'Bob'
    ..age = 25
    ..greet()
    ..birthday();
    
  print('Bob\'s age: ${p2.age}');
  
  // Nested cascades
  StringBuffer sb = StringBuffer()
    ..write('Hello')
    ..write(' ')
    ..writeAll(['Dart', '!'], ' ');
  
  print(sb.toString());
}

此示例使用 Person 类和 StringBuffer 对比了对象操作的传统符号和级联符号,展示了级联符号如何简化多个方法调用和属性赋值。

$ dart run cascade.dart
Hello, Alice!
Hello, Bob!
Bob's age: 26
Hello Dart !

赋值表达式

Dart 中的赋值表达式使用基本赋值运算符 (=) 或复合运算符(如 +=、*= 和 ~/=)将值存储在变量中。这些表达式求值为赋给的值,从而实现链式赋值。空感知赋值 (??=) 仅在变量为 null 时才赋值,提供了一种设置默认值的安全方式。

assignment.dart
void main() {

  // Simple assignment
  int x = 5;
  print('x = $x');
  
  // Compound assignment
  x += 3;
  print('x += 3 → $x');
  
  x ~/= 2;
  print('x ~/= 2 → $x');
  
  // Assignment as expression
  int y;
  print('y = ${y = x * 2}');
  
  // Null-aware assignment
  int? z;
  z ??= 10;
  print('z = $z');
}

此示例演示了简单和复合运算、将表达式作为赋值以及空感知赋值,展示了 Dart 如何管理变量更新和默认值。

$ dart run assignment.dart
x = 5
x += 3 → 8
x ~/= 2 → 4
y = 8
z = 10

表达式求值顺序

Dart 根据运算符的优先级和结合性来求值表达式。乘法等运算符的优先级高于加法,而括号会覆盖默认优先级。大多数运算符是左结合的,从左到右处理,但赋值运算符和条件运算符是右结合的,这保证了可预测的计算顺序。

evaluation_order.dart 复制
void main() {

  // Operator precedence
  int result = 2 + 3 * 4;
  print('2 + 3 * 4 = $result');
  
  // Parentheses change order
  result = (2 + 3) * 4;
  print('(2 + 3) * 4 = $result');
  
  // Left-associative operators
  result = 10 - 4 - 2;
  print('10 - 4 - 2 = $result');
  
  // Right-associative operators
  bool a = false, b = true, c = false;
  bool logical = a && b || c;
  print('a && b || c = $logical');
}

此示例说明了运算符优先级、括号的影响以及表达式求值中的结合性,展示了 Dart 如何系统地处理复杂表达式。

$ dart run evaluation_order.dart
2 + 3 * 4 = 14
(2 + 3) * 4 = 20
10 - 4 - 2 = 4
a && b || c = false

按位表达式

Dart 的按位运算符用于操作整数的位,从而实现设置标志或优化计算等底层操作。运算符包括与 (&)、或 (|)、异或 (^)、非 (~)、左移 (<<) 和右移 (>>)。这些运算符在需要直接位操作的场景(如图形处理或协议实现)中非常有用。

bitwise.dart
void main() {

  int a = 5; // Binary: 0101
  int b = 3; // Binary: 0011
  
  // Bitwise operators
  print('Bitwise AND: ${a & b}'); // 0101 & 0011 = 0001
  print('Bitwise OR: ${a | b}'); // 0101 | 0011 = 0111
  print('Bitwise XOR: ${a ^ b}'); // 0101 ^ 0011 = 0110
  print('Bitwise NOT: ${~a}'); // ~0101 = ...1010 (inverts bits)
  print('Left shift: ${a << 1}'); // 0101 << 1 = 1010
  print('Right shift: ${a >> 1}'); // 0101 >> 1 = 0010
  
  // Using bitwise for flags
  int read = 1; // 0001
  int write = 2; // 0010
  int permissions = read | write; // 0011
  print('Has read: ${(permissions & read) != 0}');
}

此示例演示了整数上的按位运算,包括与、或、异或、非和移位运算,以及一个用于管理权限标志的实际用例,突出了它们在底层编程中的实用性。

$ dart run bitwise.dart
Bitwise AND: 1
Bitwise OR: 7
Bitwise XOR: 6
Bitwise NOT: -6
Left shift: 10
Right shift: 2
Has read: true

展开运算符表达式

Dart 中的展开运算符 (...) 可以展开集合的元素,从而能够简洁地合并或复制列表、集合或映射。空感知展开运算符 (...?) 可以安全地处理 null 集合,防止运行时错误。此功能简化了表达式中的集合操作,提高了代码的可读性和灵活性。

spread.dart
void main() {

  // Spread operator with lists
  List<int> part1 = [1, 2];
  List<int> part2 = [3, 4];
  List<int> combined = [...part1, ...part2, 5];
  print('Combined list: $combined');
  
  // Null-aware spread
  List<int>? optional;
  List<int> safeList = [...part1, ...?optional, 6];
  print('Safe list: $safeList');
  
  // Spread with maps
  Map<String, int> map1 = {'a': 1, 'b': 2};
  Map<String, int> map2 = {'c': 3};
  Map<String, int> merged = {...map1, ...map2, 'd': 4};
  print('Merged map: $merged');
  
  // Nested spread
  List<List<int>> nested = [
    [1, 2],
    [3, 4]
  ];
  List<int> flattened = [...nested[0], ...nested[1]];
  print('Flattened: $flattened');
}

此示例展示了用于合并列表和映射的展开运算符、用于安全处理可空集合的空感知展开,以及展平嵌套列表,展示了其在集合表达式中的强大功能。

$ dart run spread.dart
Combined list: [1, 2, 3, 4, 5]
Safe list: [1, 2, 6]
Merged map: {a: 1, b: 2, c: 3, d: 4}
Flattened: [1, 2, 3, 4]

Switch 表达式

Dart 的 switch 表达式提供了一种根据多个条件选择值的简洁方法。与传统的 switch 语句不同,switch 表达式可以直接用于赋值和返回值,使代码更具表现力并减少样板代码。Dart 在 switch 表达式中支持模式匹配和 null 安全,从而实现了强大且可读的分支逻辑。

switch_expression.dart
void main() {

  var grade = 'B';
  var result = switch (grade) {
    'A' => 'Excellent',
    'B' => 'Good',
    'C' => 'Average',
    'D' => 'Below average',
    'F' => 'Fail',
    _ => 'Unknown',
  };
  print('Grade: $grade, Result: $result');

  // Pattern matching with types
  Object value = 42;
  var type = switch (value) {
    int i => 'Integer',
    double d => 'Double',
    String s => 'String',
    _ => 'Other',
  };
  print('Type: $type');
}

此示例演示了 Dart 的 switch 表达式用于值选择和类型模式匹配。第一个 switch 将成绩映射到描述,第二个 switch 使用类型模式来确定值的类型。Switch 表达式提高了代码的清晰度,并减少了对冗长 if-else 链的需要。

来源

Dart 语言运算符
Dart 语言之旅:表达式

掌握 Dart 表达式对于编写高效且富有表现力的代码至关重要。从字面量到级联和展开运算符等高级功能,Dart 为各种编程需求提供了多功能工具。

作者

我叫 Jan Bodnar,是一位热情的程序员,拥有丰富的经验。自 2007 年以来,我撰写了超过 1,400 篇文章和 8 本电子书,并拥有十多年的编程教学经验。

列出 所有 Dart 教程