下面的代码定义了一个带有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);