什么是 ?? Dart 中的双问号?

What are the ?? double question marks in Dart?

下面这行代码有两个问号:

final myStringList = prefs.getStringList('my_string_list_key') ?? [];

什么意思?

?? 双问号运算符表示“如果为空”。以下面的表达式为例。

String a = b ?? 'hello';

这意味着 a 等于 b,但如果 b 为空,则 a 等于 'hello'

另一个相关的运算符是??=。例如:

b ??= 'hello';

这意味着如果 b 为空则将其设置为等于 hello。否则不要改。

参考

条款

Dart 1.12 release news 统称为以下null-aware operators

  • ?? -- 如果为空运算符
  • ??= -- 空感知赋值
  • x?.p -- 空感知访问
  • x?.m() -- 空感知方法调用

Dart 提供了一些方便的运算符来处理可能为空的值。一种是 ??= 赋值运算符,它仅在该变量当前为 null 时才向该变量赋值:

int a; // The initial value of a is null.
a ??= 3;
print(a); // <-- Prints 3.

a ??= 5;
print(a); // <-- Still prints 3.

另一个 null 感知运算符是 ??,它 returns 其左侧的表达式,除非该表达式的值为 null,在这种情况下它计算 returns右边的表达式:

print(1 ?? 3); // <-- Prints 1.
print(null ?? 12); // <-- Prints 12.

这在flutter中经常用来覆盖的copyWith方法中特别有用。 下面是一个例子:

import './color.dart';
import './colors.dart';

class CoreState {
  final int counter;
  final Color backgroundColor;

  const CoreState({
    this.counter = 0,
    this.backgroundColor = Colors.white,
  });

  CoreState copyWith({
    int? counter,
    Color? backgroundColor,
  }) =>
      CoreState(
        counter: counter ?? this.counter,
        backgroundColor: backgroundColor ?? this.backgroundColor,
      );

  @override
  bool operator ==(Object other) =>
      identical(this, other) ||
          other is CoreState &&
              runtimeType == other.runtimeType &&
              counter == other.counter &&
              backgroundColor == other.backgroundColor;

  @override
  int get hashCode => counter.hashCode ^ backgroundColor.hashCode;


  @override
  String toString() {
    return "counter: $counter\n"
            "color:$backgroundColor";
  }
}