空安全迁移后List<Widget>无法强转为Iterable<SetWidget>异常怎么解决?
异常产生原因
- Dart的泛型遵循协变规则:仅子类泛型可向上转换为父类泛型,反向转换不成立。
SetWidget是Widget的子类,因此List<SetWidget>属于List<Widget>的子类型,但List<Widget>本身并非Iterable<SetWidget>的子类型,直接强制转换容器类型本身不合法。 - 空安全迁移工具仅为了通过静态语法检查自动补全了
as转换语句,并未校验运行时的实际类型匹配性:你声明的_sets容器类型为List<Widget>,即便内部存储的元素全是SetWidget,也无法直接将整个容器强转为Iterable<SetWidget>类型,因此运行时抛出类型cast异常。
处理方案
最优方案:修改容器声明类型
如果确认_sets容器内只会存储SetWidget类型的元素,直接修改变量声明即可,不需要额外添加类型转换:
// 仅修改这一行的泛型类型 final List<SetWidget> _sets = []; Map getSets() { Map sets = {}; int k = 0; // 无需加as转换,直接遍历即可 for (SetWidget set in _sets) { sets.putIfAbsent(k.toString(), () => set.getMap()); k++; } return sets; }
兼容方案:转换元素而非强转整个容器
如果无法修改_sets的声明类型,可以选择两种兼容处理方式:
- 遍历过程中逐个做类型校验,仅处理符合类型的元素,安全性最高:
Map getSets() { Map sets = {}; int k = 0; for (var element in _sets) { if (element is SetWidget) { sets.putIfAbsent(k.toString(), () => element.getMap()); k++; } } return sets; }
- 确认所有元素都是
SetWidget的前提下,使用cast方法懒转换容器元素类型:
for (SetWidget set in _sets.cast<SetWidget>()) { // 原有逻辑不变 }
注意:
cast方法仅在遍历到对应元素时才会做类型校验,如果容器内存在非SetWidget类型的元素,运行时依然会抛出类型异常。
内容的提问来源于stack exchange,提问作者Dalon
相关产品推荐
相关产品推荐

