目录

invalid_case_patterns

使用在 Dart 3.0 中有效的 case 表达式。

此规则目前是实验性的,并且从 Dart 3.0 开始可用。

此规则有可用的快速修复

详情

#

在 Dart 2.19 及更低版本中有效的一些 case 表达式,当库升级到 3.0 时,将变为错误或具有不同的语义。此 lint 标记这些表达式,以便于迁移到 Dart 3.0。

2.19 中的一些有效 switch case 在 Dart 3.0 中将变为编译错误

  • Set 字面量
  • 带括号的表达式
  • identical() 的调用。
  • 一元运算符表达式 !-~(除了整数字面量之前的 -,它是一个有效的模式并且可以)
  • 二元运算符表达式 !===&|^~/>>>>><<+-*/%<<=>>=??
  • 条件运算符 ?:
  • 字符串上的 .length 调用
  • isis! 表达式

所有这些的示例

dart
switch (obj) {
  case {1}: // Set literal.
  case (1): // Parenthesized expression.
  case identical(1, 2): // `identical()` call.
  case -pi: // Unary operator.
  case 1 + 2: // Binary operator.
  case true ? 1 : 2: // Conditional operator.
  case 'hi'.length: // .length call.
  case i is int: // is expression.
}

2.19 中的一些有效 switch case 在语法上也是有效的模式,但模式匹配行为可能与当前的常量相等行为不同。它们是

列表和 Map 字面量。列表或 Map 字面量可以作为 case 中的常量出现

dart
switch (obj) {
  case [1, 2]: ...
  case {'k': 'v'}: ...
}

目前,仅当传入的值与常量具有相同的标识时,该 case 才会匹配。所以

dart
test(List<int> list) {
  switch (list) {
    case [1, 2]: print('Matched'); break;
    default: print('Did not match'); break;
  }
}

main() {
  test(const [1, 2]); // Prints "Matched".
  test([1, 2]); // Prints "Did not match".
}

对于模式,列表或 Map 字面量将变为列表或 Map 模式。该模式会解构传入的对象,并在所有子模式都匹配时匹配。换句话说,列表和 Map 模式使用更类似于深度相等的东西进行匹配。

在 Dart 3.0 中,上述程序将打印“Matched”两次。

常量构造函数调用。与集合类似,您可以在 case 中构造类的常量实例

dart
class Point {
  final int x;
  final int y;
  const Point({this.x, this.y});
}

test(Point p) {
  switch (p) {
    case Point(x: 1, y: 2): print('Matched'); break;
    default: print('Did not match'); break;
  }
}

main() {
  test(const Point(1, 2)); // Prints "Matched".
  test(Point(1, 2)); // Prints "Did not match".
}

同样,与集合类似,仅当传入的值具有相同的标识时,该 case 当前才会匹配。对于模式,Point(...) 语法将变为对象模式,该模式会解构传入的点,对其调用 xy getter,然后将这些结果与相应的子模式进行匹配。

在此示例中,它将打印“Matched”两次。

请注意,对象模式仅支持命名字段。因此,今天 case 中具有位置参数的任何常量构造函数在解析为模式时都将变为编译时错误。没有参数的常量构造函数调用是有效的对象模式,并且仅进行类型测试

dart
class Thing {
  const Thing();
}

test(Thing t) {
  switch (t) {
    case Thing(): print('Matched'); break;
    default: print('Did not match'); break;
  }
}

main() {
  test(const Thing()); // Prints "Matched".
  test(Thing()); // Prints "Did not match".
}

当解释为模式时,这将打印“Matched”两次。

通配符。今天,您可以拥有一个名为 _ 的常量

dart
test(int n) {
  const _ = 3;
  switch (n) {
    case _: print('Matched'); break;
    default: print('Did not match'); break;
  }
}

main() {
  test(3); // Prints "Matched".
  test(5); // Prints "Did not match".
}

对于模式,标识符 _ 被视为匹配所有值的模式,因此这将打印“Matched”两次。

逻辑运算符。逻辑运算符 &&|| 是有效的常量表达式,也是有效的模式。作为常量表达式,它们只是将表达式求值为布尔值,并在传入的值等于该布尔值时匹配。所以

dart
test(bool b) {
  switch (b) {
    case true && false: print('Matched'); break;
    default: print('Did not match'); break;
  }
}

main() {
  test(false); // Prints "Matched".
  test(true); // Prints "Did not match".
}

在 Dart 3.0 中,这些将变为模式。上面的示例打印“Did not match”两次,因为没有布尔值可以同时为 true 和 false。

许多无效的 case 可以机械地更改为在今天的 Dart 中有效,并且在 Dart 3.0 中有效并且含义相同的东西。

带括号的表达式:如果内部表达式在 Dart 3.0 中没有中断,则只需丢弃括号。

列表字面量、Map 字面量、Set 字面量和常量构造函数调用:在字面量或调用之前放置 const。这会将其转换为保留当前行为的常量模式

错误

dart
case [1, 2]:
case {'k': 'v'}:
case {1, 2}:
case Point(1, 2):

正确

dart
case const [1, 2]:
case const {'k': 'v'}:
case const {1, 2}:
case const Point(1, 2):
  • 通配符:将常量从 _ 重命名为其他名称。由于该名称是私有的,因此可以在库中本地完成,而不会影响其他代码。

  • 其他一切:对于任何其他无效表达式,您必须将表达式提升为一个新的命名常量。例如,如果您有如下代码

错误

dart
switch (n) {
  case 1 + 2: ...
}

可以通过将其更改为以下内容来修复

正确

dart
const three = 1 + 2;

switch (n) {
 case three: ...
}

用法

#

要启用 invalid_case_patterns 规则,请在 analysis_options.yaml 文件中的 linter > rules 下添加 invalid_case_patterns

analysis_options.yaml
yaml
linter:
  rules:
    - invalid_case_patterns