invalid_case_patterns
使用在 Dart 3.0 中有效的 case 表达式。
详情
#在库升级到 3.0 时,一些在 Dart 2.19 及更早版本中有效的 case 表达式将成为错误或语义发生变化。此 lint 标记这些表达式,以便简化迁移到 Dart 3.0 的过程。
在 Dart 3.0 中,一些在 2.19 中有效的 switch case 将成为编译错误
- Set 字面量
- 带括号的表达式
- 调用
identical()
。 - 一元运算符表达式
!
、-
或~
(但整数文字前的-
除外,它是一个有效的模式且没有问题) - 二元运算符表达式
!=
、==
、&
、|
、^
、~/
、>>
、>>>
、<<
、+
、-
、*
、/
、%
、<
、<=
、>
、>=
、??
。 - 条件运算符
?:
- 对字符串调用
.length
is
和is!
表达式
所有这些示例
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 中
switch (obj) {
case [1, 2]: ...
case {'k': 'v'}: ...
}
目前,只有当传入值与常量具有相同的 identity 时,case 才会匹配。所以
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 中构造类的常量实例
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 当前只有当传入值具有相同的 identity 时才会匹配。使用模式时,Point(...)
语法会变成一个对象模式,它解构传入的点,调用其上的 x
和 y
getter,然后将这些结果与相应的子模式进行匹配。
在这个示例中,它将打印两次 "Matched"。
请注意,对象模式仅支持命名字段。因此,今天 case 中任何具有位置参数的常量构造函数在解析为模式时将成为编译时错误。没有参数的常量构造函数调用是一个有效的对象模式,并且只执行类型测试
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"。
通配符。 今天,您可以有一个名为 _
的常量
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"。
逻辑运算符。 逻辑运算符 &&
和 ||
是有效的常量表达式,也是有效的模式。作为常量表达式,它们仅将表达式评估为布尔值,并在传入值等于该布尔值时匹配。所以
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
。这会将其变成一个常量模式,从而保留当前的行为
不好
case [1, 2]:
case {'k': 'v'}:
case {1, 2}:
case Point(1, 2):
好
case const [1, 2]:
case const {'k': 'v'}:
case const {1, 2}:
case const Point(1, 2):
通配符: 将常量从
_
重命名为其他名称。由于该名称是私有的,因此可以在库中本地完成,而不会影响其他代码。所有其他情况: 对于任何其他无效表达式,您必须将表达式提升到一个新的命名常量。例如,如果您有以下代码
不好
switch (n) {
case 1 + 2: ...
}
可以通过将其更改为以下内容来修复
好
const three = 1 + 2;
switch (n) {
case three: ...
}
启用
#要启用 invalid_case_patterns
规则,请在您的 analysis_options.yaml
文件中的 linter > rules 下添加 invalid_case_patterns
linter:
rules:
- invalid_case_patterns
如果您正在使用 YAML map 语法配置 linter 规则,请在 linter > rules 下添加 invalid_case_patterns: true
linter:
rules:
invalid_case_patterns: true