Dart firstWhere或Else:泛型函数返回类型



下面的代码定义了一个带有3个参数的通用myFirstWhereFunction:

  • 一般列表
  • 要在列表中搜索的常规值
  • 如果搜索的值不在传递的泛型列表中,则返回的泛型默认值

代码:

void main() {
const List<int> intLst = [1, 2, 3, 4];
print(myFirstWhereFunc(intLst, 4, -1));
print(myFirstWhereFunc(intLst, 5, -1));
const List<String> strLst = ['coucou', 'go', 'bold', 'tooltip'];
print(myFirstWhereFunc(strLst, 'go', 'not exist'));
print(myFirstWhereFunc(strLst, 'ok', 'not exist'));
}
T myFirstWhereFunc<T>(List<T> lst, T searchVal, T defaultVal) {
return lst.firstWhere((element) => element == searchVal, orElse: <T> () {
return defaultVal;
});
}

但这段代码会生成一个异常。

一种解决方案是用动态(下面的代码(替换通用myFirstWhereFunc返回类型:

dynamic myFirstWhereFunc<T>(List<T> lst, T searchVal, T defaultVal) {
return lst.firstWhere((element) => element == searchVal,
orElse: () => defaultVal);
}

但是,还有其他解决问题的方法吗?

我认为问题在于当你这样做时:

print(myFirstWhereFunc(intLst, 4, -1));

有两种可能的方法来推断myFirstWhereFunc的类型:

  • 自下而上(由内而外(:使用List<int>int参数调用myFirstWhereFunc,因此其类型可以是myFirstWhereFunc<int>。这就是你想要的
  • 自上而下(outside in(:print有一个Object?参数,所以myFirstWhereFunc可以是myFirstWhereFunc<Object?>,所以它返回一个Object?。这就是实际发生的事情,也是你不想要的

Dart最终提供了两种可能的方法来推断泛型类型参数,这两种方法在编译时似乎同样有效,并且它选择了您碰巧不想要的方法。对于不同的代码示例,选择另一种方法可能会导致不希望的结果。可以说,如果一种方法导致另一种方法的子类型,推理可以同时尝试两种方法,并选择更窄的类型。我不确定这是否会破坏代码,但我不会感到惊讶。(我还怀疑https://github.com/dart-lang/language/issues某处…(

myFirstWhereFunc的返回类型更改为dynamic是解决该问题的一个粗略方法,因为这会使myFirsyWhereFunc的类型不再可以从print的参数类型中推断出来。

如果您将行拆分并使用临时变量,则推断可以独立于print推断myFirstWhereFunc,然后应该执行您想要的操作:

var intResult = myFirstWhereFunc(intLst, 4, -1);
print(intResult);

最新更新