你好,当我使用这个通用方法时,出现了以下错误:
'num'类型的值不能被分配给'T'类型的变量。尝试更改变量的类型,或将右侧类型转换为'T'。
这里的错误是什么?
sums<T extends num>(List<T> list) {
T res =list[0];
for (var i = 1; i < list.length; i++) {
res = res + list[i];
}
print(res);
}
res = (res + list[i]) as T;
这种写法是一种强制类型转换。如果您只是写res = res + list[i] as T;
,则as
的优先级意味着它与上面的强制转换相同。
在Dart 2.10.x中,它可以不需要显式强制转换的原因是语言会为您插入一个隐式强制转换。
如果您写res += list[i] as T;
,它的意思是res = res + (list[i] as T);
,这是一次不必要的强制转换,因为list[i]
已经有了类型T
,并且并不强制转换加法的结果。
这不会每次都失败int res = ...; res = res + otherInt;
是因为语言规范特殊处理了int.operator+
(以及一些类似的整数运算符),并且识别出结果是否为整数,即使+
运算符的返回类型是num
。但这种特殊情况不适用于T extends num
。
void main() {
final nums = [1, 2.0, 3.5];
final ints = [1, 2, 3];
final doubles = [1.1, 2.2, 3.3];
sums(nums);
sums(ints);
sums(doubles);
}
void sums<T extends num>(List<T> list) {
T res = list[0];
for (var i = 1; i < list.length; i++) {
res = res + list[i];
}
print(res);
}
我遇到了您提到的错误:
main.dart:14:9: Error: A value of type 'num' can't be assigned to a variable of type 'T'.
res = res + list[i];
^
然而,如果我在Dart 2.10.5中运行相同的代码,程序可以编译并正常运行,我会得到以下输出:
6.5
6
6.6
List
的类型推断存在问题。它似乎没有采用传递给sums
的实际类型参数,而是采用了类型限制num
作为其推断类型。因此,类型系统看到你正在将一个num
加到一个T extends num
上,然后将其赋值给后者。(为了解释这一点,想象一下T
是int
。一个num
加上一个int
会得到一个num
。然后试图将其分配给int
会导致类型错误,因为对于所有类型系统知道的情况来说,num
实际上可能是一个double
。)list
的元素强制转换为T
,错误就会消失。void sums<T extends num>(List<T> list) {
T res = list[0] as T;
for (var i = 1; i < list.length; i++) {
res = res + list[i] as T;
}
print(res);
}
// Prints:
//
// 6.5
// 6
// 6.6
void sums<T extends num>(List<T> list) {
T res = list[0];
for (var i = 1; i < list.length; i++) {
res += list[i] as T;
}
print(res);
}
// Prints:
//
// main.dart:14:9: Error: A value of type 'num' can't be assigned to a variable of type 'T'.
// res += list[i];
// ^
编辑:我已在Dart SDK Github页面上为此主题提交了一个问题。
编辑2:结果表明,这不是一个错误,而是作为Dart 2.12的一部分进行的有意更改的结果。有关详细信息,请参见Irn的答案。