【发布时间】:2018-09-07 13:49:29
【问题描述】:
在我的问题Dart 2.X List.cast() does not compose 中,答案需要将List<dynamic> 转换为List<String>,如下所示:
List<String> ls = (json['data'] as List).cast<String>().map((s) => s.toUpperCase()).toList();
我的其他语言经验让我先写了这个:
List<String> ls = (json['data'] as List<String>).map((s) => s.toUpperCase()).toList();
请注意,这会编译,但在 Dart 2 中运行时会失败。
为什么 List 的 Dart 类型转换需要函数 as List).cast<String>() 而不是简单地使用 Dart as “类型转换运算符”,例如 as List<String>?
---- 编辑----
我正在使用最新的 Dart 2.0.0-dev.43.0 并使用 as 类型转换/断言获得不一致的运行时行为。 .cast<>() 函数创建新的可迭代对象与.map() 不一样吗?将我的代码更改为此有效:
List<String> ls = (json['data'] as List).map((s) => (s as String).toUpperCase()).toList();
这似乎利用了List 的第一个演员是List<dynamic>。因此.map 函数参数也是dynamic。
我上面的第二个例子 as List<String> 在我们代码的某些地方工作,但在其他地方却不行。请注意,IntelliJ 正确推断了上述所有示例中的类型 - 它是发生故障的运行时。我猜测不一致的行为是由于 Dart 2.x 仍在开发中。
----第二次编辑----
这是我在一个类构造函数中的测试用例:
Map<String, dynamic> json = { "data": ["a", "b", "c"] };
//List<String> origBroken = json["data"].map( (s) => s.toUpperCase() ).toList();
// Sometimes works - sometimes gives "Ignoring cast fail from JSArray to List<String>" at runtime!!!
List<String> wonky = (json["data"] as List<String>).map( (s) => s.toUpperCase() ).toList();
print("Wonky $wonky");
List<String> fix1 = (json["data"] as List).cast<String>().map( (s) => s.toUpperCase() ).toList();
List<String> fix2 = (json["data"] as List).map( (s) => (s as String).toUpperCase() ).toList();
List<String> explicit2 = (json["data"] as List<dynamic>).map( (dynamic s) => (s as String).toUpperCase() ).toList();
// From accepted answer of the linked question - compile error because .cast() doesn't take parameters
// error: Too many positional arguments: 0 expected, but 1 found.
//List<String> notBroken = (json['data'] as List).cast<String>((s) => s.toUpperCase()).toList();
List<String> notBrokenFixed = (json['data'] as List<String>).cast<String>().map((String s) => s.toUpperCase()).toList();
问题是 Ignoring cast fail from JSArray to List<String> 有时由 wonky 赋值给出的警告。当我说有时是因为当我对使用包含此代码的库的主应用程序进行更改时,它会发生不可预测的变化 - 而不对此类甚至库进行更改。
在我编写上述第一个编辑时,wonky 无法正常工作。我现在又试了一次,它正在工作。我没有更改此库中的任何代码 - 我一直在依赖于此代码库的主应用程序中工作。
一些背景知识,这是一个从 Angular/Typescript 转换而来的多库项目。这些测试用例基于我们将 JSON 反序列化为 Dart 类的处理。我们使用类构造函数初始化器将 JSON(动态)字符串映射到各种数据结构,例如枚举、Option 和 Either(来自 dartz)。
几周前,运行时警告开始发生,我相信是因为Breaking Change: --preview-dart-2 turned on by default。
我知道这个警告很快就会出错。所以我将警告追溯到这些从 JSON 动态数据映射的转换(是的,动态数据是 Dart 中的一个边缘情况,但它是 dart:convert 提供的)。
我们正在使用 DDC 和最新的 Dart 2.0.0-dev.43.0、angular 5.0.0-alpha+8、build_runner 0.8.0、IntelliJ 2018.1 在 Mac 上进行开发,并在 Chrome 65.0.3325.181 上运行。
----最终编辑----
导致此问题的当前开发构建/运行时存在不稳定性。不,我没有可重现的例子。更改和重建我们的主应用程序会导致此代码在未修改的库依赖项中有时会发出运行时警告Ignoring cast fail from JSArray to List<String>。
来自这个问题原始部分的可疑代码(也是上面的wonky)
List<String> ls = (json['data'] as List<String>).map((s) => s.toUpperCase()).toList();
将动态 JSON 数据转换为 List<String>。类型受到完全限制,Dart 分析器/IntelliJ 将 s 推断为 Static type: String。
有时出现的运行时警告和使用.cast() 的相关答案是导致这个问题的原因。这时候我会相信分析器并忽略运行时警告。
【问题讨论】:
-
“在我们代码的某些地方有效,但在其他地方无效。”您能否提供具体的例子,其中它不起作用以及具体错误是什么?
标签: dart