You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Dart中按引用传递的Future为何哈希值不同、比较结果为false?

Dart中Future比较不相等的原因分析及修正

问题核心

你第一个实验的逻辑是对的:当两个变量指向同一个Future实例时,引用相等,==返回true。但第二个实验的问题出在async函数的特性上,你忽略了async函数每次调用都会生成新的Future实例。

错误原因拆解

  1. async函数的默认行为:
    只要调用标记为async的函数,Dart会立即创建一个全新的Future实例作为函数返回值,不管你在函数内部return的是什么值(包括另一个Future)。这个新Future会等待你return的对象完成,然后传递其结果,但它本身是独立的实例。

  2. 你的代码具体问题:

    • 第一次调用processFuture()时,async函数返回一个新Future(记为F1),也就是d1指向的实例。函数内部创建了_future,并await它。
    • 第二次调用processFuture()时,虽然进入了if (_future != null)分支并return _future,但async函数会把这个return的_future包装成另一个全新的Future(记为F2),也就是d2指向的实例。
    • F1和F2是两个不同的对象,所以哈希值不同,d1 == d2返回false。

    补充说明:init()里的两次processFuture()调用是同步执行的,此时第一次调用里的await _future还没执行到(因为Future.delayed是异步的),所以第二次调用时_future确实不为null,但返回的依然是新的Future实例。

修正方案

要实现复用同一个Future的目标,需要让processFuture()直接返回_future实例,避免async函数的自动包装。可以把函数改成非async,用whenComplete处理后续逻辑:

void main() {
  Test();
}

class Test {
  Future? _future = null;

  Test() {
    init();
  }

  void init() {
    print("CALL 1");
    Future d1 = processFuture();
    print("ISNULL? "+(_future == null).toString());
    print("CALL 2");
    Future d2 = processFuture();
    print("ISNULL? "+(_future == null).toString());
    print(d1.hashCode);
    print(d2.hashCode);
    print(d1 == d2); // 现在会返回true
  }

  Future processFuture() {
    print("CALLED processFuture()");
    if (_future != null){
      print("FUTURE IS ALREADY THERE");
      return _future!;
    }
    print("NEW FUTURE REQUESTED");
    _future = Future.delayed(const Duration(seconds: 1))
        .whenComplete(() {
          print("FUTURE COMPLETE");
          _future = null;
          print("FUTURE IS NOW NULL");
        });
    print("NEW FUTURE CREATED");
    return _future!;
  }
}

这样修改后,两次调用processFuture()返回的都是同一个_future实例,d1 == d2会返回true,达到复用Future的目的。

内容的提问来源于stack exchange,提问作者g.imtech

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 02:48:21