首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >类型'num‘的值不能赋值给'T’类型的变量

类型'num‘的值不能赋值给'T’类型的变量
EN

Stack Overflow用户
提问于 2021-03-20 19:39:06
回答 2查看 14.3K关注 0票数 2

当我使用这个通用方法时,我会得到这个错误。

类型'num‘的值不能分配给'T’类型的变量。尝试更改变量的类型,或将右侧类型转换为“T”。

这里的错误是什么

代码语言:javascript
复制
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);
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-03-20 21:01:49

这似乎是Dart 2.12+的一个bug或一个误解的特性。在这两种情况下,可能都值得在Dart Github页面上打开一个问题。

如果我在2.12.0中运行以下代码:

代码语言:javascript
复制
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);
}

我知道你提到的错误:

代码语言:javascript
复制
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中运行相同的代码,程序编译和运行就没有问题,并得到以下打印输出:

代码语言:javascript
复制
6.5
6
6.6

我最好的猜测是,在涉及List的类型参数时,类型推断存在一个问题。它不是接受传递给sums的实际类型参数,而是将类型约束num作为它的推断类型。因此,类型系统看到您正在向一个num中添加一个T extends num,然后将它分配给后者。(为了解释,假设Tint。一个num加上一个int将导致num。尝试将其分配给int会导致类型错误,因为对于所有类型系统都知道,num实际上可能是一个double。)

无论如何,一旦您执行错误建议并将list的元素转换为T,错误就会消失。

代码语言:javascript
复制
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

然而,有趣的是,使用加法分配会导致相同的错误,而不管强制转换是什么:

代码语言:javascript
复制
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:原来这不是一个bug,而是作为2.12的一部分对Dart的预期更改的结果。详见欧文的回答。

票数 2
EN

Stack Overflow用户

发布于 2021-03-21 22:13:00

这里的问题是,Dart在Dart 2.12.0中引入的新的Null安全特性消除了语言中的隐式降级。

如果res具有T类型T extends num,则操作res + something具有静态类型num。关于T,我们只知道它实现了numnum.operator+返回了num。但是,num不能分配给T extends num,因为后者是前者的一个子类型(T可以是int,并不是所有的num值都可以分配给int)。因此,需要显式强制转换才能使赋值有效:

代码语言:javascript
复制
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.

票数 8
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66725731

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档