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

如何判断Dart中两个函数是否相等?实现唯一函数列表

Dart中检测函数实例唯一性的问题及解决方案

问题原因

你遇到的核心问题是:Dart里每次在循环内部定义函数时,都会生成一个全新的闭包实例。哪怕函数的代码逻辑完全一致,这些实例的引用地址也不相同。而List.contains()方法默认用==判断,函数的==是比较引用身份,所以每次检测都会返回false,导致重复添加。同理,每个闭包的hashCode都是唯一的,靠哈希值检测也没用。

而把函数定义移到循环外时,整个循环引用的是同一个函数实例,所以contains能正确识别,最终列表长度为1。

可行解决方案

因为循环内生成的闭包本质是不同实例,无法通过默认的身份判断来识别“逻辑相同”的函数,所以需要换一种思路去重:

1. 用包装类绑定唯一标识

创建一个包装类,把函数和一个业务层面的唯一标识绑定,存储包装类而非直接存函数。去重时比较标识而非函数实例:

import 'package:flutter/widgets.dart';

class ListenerWrapper {
  final String uniqueKey;
  final VoidCallback callback;

  ListenerWrapper(this.uniqueKey, this.callback);
}

// 使用示例
final listeners = <ListenerWrapper>[];
for (int i = 0; i < 5; i++) {
  void listener() => setState(() {});
  // 根据业务逻辑生成唯一key,比如关联的组件ID、事件名称等
  final wrapper = ListenerWrapper('refresh_state_listener', listener);
  if (!listeners.any((item) => item.uniqueKey == wrapper.uniqueKey)) {
    listeners.add(wrapper);
  }
}

2. 让调用者提供唯一标识

作为库开发者,可以要求用户在注册监听器时传入一个唯一key,以此作为去重依据。这是很多第三方库的通用做法:

final listeners = <MapEntry<String, VoidCallback>>[];

void addListener(String key, VoidCallback callback) {
  if (!listeners.any((entry) => entry.key == key)) {
    listeners.add(MapEntry(key, callback));
  }
}

// 调用示例
for (int i = 0; i < 5; i++) {
  addListener('refresh_state', () => setState(() {}));
}

注意:不推荐的方式

不要尝试通过反射(dart:mirrors)获取函数源代码来比较,一来Flutter环境禁用了反射,二来逻辑相同但作用不同的函数可能源代码一致,容易误判。

内容的提问来源于stack exchange,提问作者buttonsrtoys

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 14:55:25