为什么 dart 错误地推断出我的泛型参数类型? [英] Why is dart wrongly inferring my generic parameter type?

查看:45
本文介绍了为什么 dart 错误地推断出我的泛型参数类型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我似乎无法理解为什么 mySet 变量被推断为具有动态参数类型的泛型集,当我清楚地将它等同于一个 int 集文字时.那么这个结果是合乎逻辑的还是 dart 真的无法推断泛型集参数类型?

main(){设置 mySet = {1 ,2 , 3};var myProducts = {1:'电视',2:'冰箱',3:mySet.lookup(2),4:'平板电脑',5:'计算机'};var userCollection = {"name":"John Smith","Email":"john@sanjib.site"};myProducts.forEach((x,y) => print("${x} : ${y}"));userCollection.forEach((k, v) => print("${k} : ${v}"));}

解决方案

如果你声明一个具有泛型类型 Generic 的变量但省略了参数化类型,它是 (通常是1) Generic 的简写.推理确实发生在你的作业中,但不是你期望的方向:因为你明确声明了 mySet 的类型,{1, 2, 3 的类型} 是从那个显式类型 (Set/Set) 推断出来的,变成 {1, 2, 3} 而不是 {1, 2, 3}.

这就是为什么最好省略显式类型而只允许在可能的情况下推断类型的原因之一.使用:

var mySet = {1, 2, 3};

允许将 mySet 推断为 Set.如果你真的想使用显式类型,你应该确保你也为泛型类型参数指定了显式类型.

您可以通过设置来捕获此类错误:

分析器:语:严格原始类型:true

在您的 analysis_options.yaml 文件中.(您可能还希望启用:

分析器:强模式:隐式转换:false隐式动态:假

也是.)

另见https://github.com/dart-lang/language/blob/master/resources/type-system/strict-raw-types.md:

<块引用>

void main() {列表 a = [1, 2, 3];}

开发者通常认为推理是从赋值的右侧填入a的类型.它可能看起来像 a 的类型 List.但是 Dart 填充省略的类型参数,例如 List 上的 E,带有 dynamic(或相应类型参数的绑定);List a; 纯粹是 List 的简写.一个;.推理然后从 a 流向赋值右侧的表达式.


1 严格来说,如果泛型的类型参数受到约束(例如 class Generic),则省略类型参数是使用该约束的简写(即,GenericGeneric 的简写).大多数泛型不限制它们的类型参数,因此它通常以动态结束.

I can't seem to understand why the mySet variable is being inferred as a generic set with dynamic parameter type, when I clearly equated it to an int set literal. So is this result logical or has dart genuinely failed to infer the generic sets parameter type?

main(){
  Set mySet = {1 ,2 , 3};
  var myProducts = {
    1:'TV',2:'Refrigerator',
    3:mySet.lookup(2),
    4:'Tablet',
    5:'Computer'
    };
    var userCollection = {"name":"John Smith","Email":"john@sanjib.site"};
    myProducts.forEach((x,y) => print("${x} : ${y}"));
    userCollection.forEach((k, v) => print("${k} : ${v}"));
}

解决方案

If you declare a variable with a generic type Generic but omit the parameterized type, it's (usually1) shorthand for Generic<dynamic>. Inference does happen in your assignment, but not in the direction you expect: since you explicitly declared the type of mySet, the type of {1, 2, 3} is inferred from that explicit type (Set/Set<dynamic>) and becomes <dynamic>{1, 2, 3} instead of <int>{1, 2, 3}.

This is one reason why it can be better to omit explicit types and just allow types to be inferred when possible. Using:

var mySet = {1, 2, 3};

would allow mySet to be inferred as Set<int>. If you really want to use explicit types, you should ensure that you specify explicit types for generic type parameters too.

You can catch such errors by setting:

analyzer:
  language:
    strict-raw-types: true

in your analysis_options.yaml file. (You also might wish to enable:

analyzer:
  strong-mode:
    implicit-casts: false
    implicit-dynamic: false

too.)

Also see https://github.com/dart-lang/language/blob/master/resources/type-system/strict-raw-types.md:

void main() {
  List a = [1, 2, 3];
}

Developers often think that inference fills in the type of a from the right side of the assignment. It may look like a has the type List<int>. But Dart fills in omitted type arguments, like E on List, with dynamic (or the corresponding type parameter's bound); List a; is purely a shorthand for List<dynamic> a;. Inference then flows from a onto the expression on the right side of the assignment.


1 Strictly speaking, if a generic's type parameter is constrained (e.g. class Generic<T extends Base>), then omitting the type parameter is shorthand for using that constraint (i.e., Generic would be shorthand for Generic<Base>). Most generics don't constraint their type parameters, so therefore it usually ends up being dynamic.

这篇关于为什么 dart 错误地推断出我的泛型参数类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆