为什么 Dart 中显式使用“.cast<>()”函数而不是“as <>”

2024-01-07

在我的问题中Dart 2.X List.cast() 不组合 https://stackoverflow.com/questions/49539879/dart-2-x-list-cast-does-not-compose答案需要转换List<dynamic> to a 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 中运行时会失败。

为什么 Dart 类型转换为List需要一个函数as List).cast<String>()而不是简单地使用 Dartas“类型转换运算符”,例如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 is a 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)。

几周前,运行时警告开始发生,我相信是因为重大更改:--preview-dart-2 默认打开 https://groups.google.com/forum/#!topic/flutter-dev/H8dDhWg_c8I。 我知道这个警告很快就会变成错误。因此,我将警告追溯到这些从 JSON 动态数据映射的转换(是的,动态数据是 Dart 中的边缘情况,但这就是dart:convert提供)。

我们正在 Mac 上使用 DDC 进行开发,其中包含最新的 Dart 2.0.0-dev.43.0、Angular 5.0.0-alpha+8、build_runner 0.8.0、IntelliJ 2018.1,并在 Chrome 65.0.3325.181 上运行。

---- 最终编辑 ----

此问题背后的当前开发构建/运行时存在不稳定。不,我没有可重现的例子。更改和重建我们的主应用程序将导致未修改的库依赖项中的此代码有时会发出运行时警告Ignoring cast fail from JSArray to List<String>.

这个问题原始部分的可疑代码(也wonky above)

List<String> ls = (json['data'] as List<String>).map((s) => s.toUpperCase()).toList();

将动态 JSON 数据转换为List<String>。类型受到完全约束,Dart 分析器/IntelliJ 推断s to be Static type: String.

有时出现的运行时警告及相关使用解答.cast()是什么导致了这个问题。这时我会相信分析器并忽略运行时警告。


在 Dart 2 中,泛型类型被具体化。

as ...如果值类型不匹配,则更像是断言as导致运行时异常。

cast<T>()是 Dart 2 中引入的方法Iterable这实际上创建了一个新的可迭代类型Iterable<T>(或者在你的情况下子类List<T>)填充原始可交互的值。


Update

您可以使用print('wonky: ${wonky.runtimeType}');查看实际类型是什么。

如果类型符合您的要求,您可以使用as向分析器传达可以安全地采用这种类型的信息。

如果类型不匹配,例如因为它是List代替List<String>,那么你可以使用.cast<String>()实际上使它成为List<String>.

List<String> broken = (json['data'] as List)
  .cast<String>((s) => s.toUpperCase()).toList();

在这里你似乎尝试使用cast用于投射和映射,但这无效。map()不过可以两者兼得

List<String> notBroken = (json['data'] as List)
  .map<String>((s) => s.toUpperCase()).toList();
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么 Dart 中显式使用“.cast<>()”函数而不是“as <>” 的相关文章

随机推荐

  • Typescript 创建模块

    我想为我们的库创建模块 所以每次我们调用时 我们都可以使用import Api Map from ourlibrary 目前我正在使用以下 import Api from Library Api import MapPage from ma
  • 非常非常大的实体组的交易

    我正在尝试设计一个可以容纳大量数据的数据模型 有大量数据经验的人对此有什么反馈吗 即 example only not meant to compile public class TransactionAccount private lon
  • 如何对每小时时间序列重新采样以在特定时间开始并在 24 小时后结束

    我想从一天中的特定时间开始 在我的情况下 将从 2020 年 2 月 1 日 06 UTC 开始 对我的数据框进行重新采样 包括每小时降水量值 频率为 24 小时 2020 02 01 每小时数据帧图像 I tried df df resa
  • PHP,如何重定向/转发带标头和正文的 HTTP 请求?

    我有一个 PHP 页面 main php 位于服务器 1 上 我在服务器 2 上有一个 PHP 页面 main php 同一页面 不同的代码 main php 是一个 Web 服务 我想转发对服务器 1 服务器 2 发出的完整 HTTP 请
  • Angular - 生成的表格单元格上的(单击)事件

    我一直在尝试在动态生成的表格中的单元格上添加 单击 事件 HTMLtoAdd any Input roles string ngOnInit let alphabet A B C D E F G H I J K L M N O P Q R
  • 如何用类创建div

    我正在尝试创建一个 div 并给他上一堂课 但它不起作用 有人可以帮助我吗 document ready function input type checkbox each function this after div div class
  • Vue.js - 如何将 props 传递给孙子

    我有以下应用程序结构 RegistrationView holds the data logic like get post RegistrationForm holds the form Registration Radio Compon
  • 使用 JSch 跳过 Kerberos 身份验证提示 [重复]

    这个问题在这里已经有答案了 我正在使用Connect 方法中的Ssh下面的 Java 类用于使用 SSH JSch 连接到服务器并在服务器中运行命令 问题是运行时Connect 服务器提示以下消息 Kerberos username Ker
  • clojure 中惯用的文件锁定?

    我有一组来自队列的 future 处理作业 涉及写入文件 确保一次只有一个未来访问特定文件的惯用方法是什么 使用代理而不是锁来确保这一点怎么样 我认为使用代理来保护共享的可变状态 无论它是在内存中还是在磁盘上 在 clojure 中比使用锁
  • 活动标题语言有问题

    我的应用程序中有两种语言 值 strings xml and 值 ru strings xml当我以编程方式更改语言时 所有字符串都会翻译 但活动标题不变 我在所有活动中使用 SharedPreferences prefs Preferen
  • 如何对列表使用二分查找

    让我们从 List BinarySearch 的重载开始 public int BinarySearch T item IComparer
  • 无法在 Android 中导入 com.google.cloud.speech.v1.SpeechGrpc

    我正在尝试使用谷歌的语音API https github com GoogleCloudPlatform android docs samples tree master speech Speech在Android项目中 示例项目有效 我在
  • Kendo Grid:工具栏模板问题

    我有一个列出道路信息的网格 并且需要一个工具栏模板 该模板允许我通过从 DropDownList 中选择特许权来过滤道路 像这样的东西 http demos telerik com aspnet mvc grid toolbar templ
  • 如何在服务器上运行java程序?

    我制作了一个 java 应用程序 将 csv 文件中的数据存储到 MySql 数据库中 现在我的客户希望它将此应用程序上传到他的网络空间 他为其网站占用的网络空间 以便他可以在该服务器上运行该程序 我用过FileZilla软件将程序上传到他
  • exoplayer 示例上的自定义 UI

    我真的需要帮助 如果你什么都不知道 请不要给我负面评价 如果有什么困扰你评论 我想在 Exoplayer 中为我的播放器编写自定义 UI 更改暂停播放按钮或添加新按钮 例如播放器速度下一个等 我使用 github 上的 Exoplayer
  • 如何在共享点中创建子列表

    是否可以在共享点中创建子列表 我目前正在使用文件夹来组织我的内容 但在以编程方式访问文件夹时 文件夹在共享点中是完全不同的概念 我想实现类似的目标 web 名单A 子列表1 子列表2 B表 子列表1 子列表2 EDIT 1 我正在尝试在网络
  • 使用 javascript 从数组中存在的字符串中删除双引号

    我有一个像这样的数组 数组 苹果 橙子 梨 我想删除数组中每个字符串开头和结尾的双引号 数组 苹果 橙子 梨 我尝试循环遍历数组的每个元素并进行字符串替换 如下所示 for var i 0 i lt array length i array
  • 如何一次关闭所有打开的选项卡?

    如果我打开了 10 个选项卡 我必须分别使用 q 关闭每个选项卡 我怎样才能一次性关闭它们呢 最短 最简单 最快的方法是 qa 要保存所有选项卡中的工作并退出 wqa
  • 在 Internet Explorer 中输入文件长度

    我想获取为输入文件选择的文件数 在 HTML 中 我有
  • 为什么 Dart 中显式使用“.cast<>()”函数而不是“as <>”

    在我的问题中Dart 2 X List cast 不组合 https stackoverflow com questions 49539879 dart 2 x list cast does not compose答案需要转换List