当前位置: 首页 > 知识库问答 >
问题:

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

慕逸仙
2023-03-14

在我的问题Dart 2中。X List.cast()不组成答案需要转换List

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类型转换需要一个函数作为List). cast

----编辑----

我使用的是最新的Dart 2.0.0-dev.43.0,运行时行为与as类型转换/断言不一致。这不是吗。铸造

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

这似乎利用了第一次强制转换到List是一个List

我上面的第二个例子是将作为List

----第二版----

下面是我的一个类构造函数中的测试用例:

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();

问题是警告忽略从JSArray到List的强制转换失败

在我写上面的第一个编辑时,wanky不起作用。我刚刚又试了一次,它起作用了。我没有改变这个库中的任何代码——我一直在依赖于这个代码库的主应用程序中工作。

在某些背景下,这是一个从Angular/Typescript转换而来的多库项目。这些测试用例基于我们将JSON反序列化为Dart类所做的处理。我们将JSON(动态)字符串映射到各种数据结构中,如枚举、选项

几周前,运行时警告开始发生,我相信是因为中断更改:--preview-dart-2默认打开。我知道这个警告很快就会出错。所以我将警告追溯到从JSON动态数据映射的这些转换(是的,动态数据在Dart中是一个边缘情况,但它是dart:转换提供的)。

我们正在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上运行。

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

此问题背后的当前开发构建/运行时存在不稳定性。不,我没有可复制的例子。更改和重建主应用程序将导致未修改库依赖项中的此代码有时发出运行时警告忽略从JSArray到List的强制转换失败

此问题原始部分中的可疑代码(也就是上面的wonky

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

将动态JSON数据转换为List

有时出现的运行时警告以及要使用的相关答案。cast()就是导致这个问题的原因。此时,我将相信分析器并忽略运行时警告。


共有1个答案

邵麒
2023-03-14

在Dart中,2个通用类型被具体化。

作为 不匹配,则code>更像是一个断言,因为会导致运行时异常。

施放

使现代化

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

如果类型符合您的需求,您可以使用作为向分析器传达假定此类型是安全的。

如果类型不匹配,例如,因为它是List而不是List

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

在这里,您似乎试图使用cast进行强制转换和映射,但这是无效的<代码>映射()可以同时执行这两项操作

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

 类似资料:
  • 我的讲师在课堂上问过我这个问题,我想知道为什么是宏而不是函数?

  • 在Julia中,打印格式化字符串的语法如下: 为什么是宏而不是函数?这样它就可以接受不同数量的参数了吗?

  • 问题内容: 我在这里找不到任何合理的答案,所以我希望它不会重复。那么为什么我应该更喜欢setter或构造函数注入而不是简单注入 如果您在类初始化期间需要对注入的bean进行某些操作,则可以使用构造函数注入的用法 但是仍然,它几乎和方法一样,并且我完全不会进行setter注入,这不只是Spring和其他DI框架之后的遗物吗? 问题答案: 构造函数和属性注入使您可以轻松地在非CDI环境中(例如,单元测

  • 我碰巧知道,在下面的表达式中,使用将导致无限流,将始终为0。我之所以困惑是因为我认为返回的值没有被使用,即便如此,它也不应该中断之后的增量。

  • 很多人问了此问题,说bzero已经被posix-2008废弃,为何还使用bzero。选择bzero而不是memset,有2个原因: bzero有2个参数,指针和长度,很明确就是将制定size的内存初始化为0。而memset有3个参数,需要记忆参数的位置,有不少人经常把长度和初始化值搞错。 bzero比memset的可读性要好。memset可以制定初始化的值,实际上绝大多数情况都是0。 一旦新版本g

  • 问题内容: 我知道python具有用于确定字符串大小的函数,但是我想知道为什么它不是字符串对象的方法。 更新资料 好吧,我意识到我是一个尴尬的错误。实际上是字符串对象的方法。在字符串对象上使用len函数在Python中看到面向对象的代码似乎很奇怪。此外,看到名字而不是len也很奇怪。 问题答案: 字符串确实有一个length方法: Python中的协议是在具有一定长度并使用内置函数的对象上实现此方