Dart中的隐式强制转换与"as"关键字之间有区别吗?



在dart中使用隐式强制转换与关键字"as"有什么区别吗?如果类型不符合预期,它们会导致相同(或类似(的运行时错误吗?

例如:

dynamic foo = "blah";
String boo = foo; // is this
String boo2 = foo as String; // the same as this?

否。是的。TL;DR:别担心有什么不同,只要读得最好就行了。

如果您的程序是正确的,并且强制转换将成功,那么就不太可能有任何差异。

在推断类型时,String boo = foo;将推断上下文类型为Stringfoo的类型。如果foo的结果静态类型是dynamic,则它意味着从dynamic到`String的隐式下变频。

对于String boo = foo as String;,在没有上下文类型的情况下推断出foo的静态类型。无论生成的静态类型是什么,都将在运行时强制转换为String

如果你有一个比变量foo:更复杂的表达式,你可以看到这两者之间的区别

T first<T extends dynamic>(List<T> list) => list.first;
String boo = first([1]); // <- compile-time error
String boo2 = first([1]) as String;

在本例中,由于编译器知道列表应该是List<String>,因此在boo行中会出现编译时错误。boo2行中没有错误,因为列表只需要是List<dynamic>,然后无论first返回什么,都会动态地转换为String

一个更人为的例子是:

T firstOrDefault<T extends dynamic>(List<T> list) {
if (list.isEmpty) {
// Invent some default values for known types.
if (null is T) return null as T;
if (0 is T) return 0 as T;
if (0.0 is T) return 0.0 as T;
if ("" is T) return "" as T;
if (false is T) return false as T;
throw UnsupportedError("No default value for the needed type");
}
return list.first;
}
String boo = firstOrDefault([]); // <- returns "", with null safety.
String boo2 = firstOrDefault([]) as String; // <- returns null, throws.

(不建议使用这种类型参数专门化编程风格。它太脆弱了,正是因为静态类型的细微变化会以不可预测的方式影响它。(。

忽略推理和静态检查,在运行时没有太大的差异。如果foo只是一个静态类型为dynamic的简单表达式,那么在这两种情况下,该语言都需要向下转换为String

然而,Dart2JS web编译器可以启用不健全的优化。这些优化基本上完全省略了隐式下转换(作为"优化",假设它们会成功(,并继续使用可能类型不健全的值。出于这个原因,有些人(主要是那些为网络编码的人(可能更喜欢使用隐式下转换而不是显式下转换。

安全性为空的Dart仅具有来自dynamic的隐式下转换。您总是可以通过执行以下操作来强制从任何类型进行隐式向下转换:

String boo3 = foo as dynamic;

as dynamic是一个自由转换,它在运行时没有影响(它不会失败,编译器知道这一点(,所以它所做的只是更改表达式的静态类型。。。引入了一个隐式下转换,然后dart2js编译器也会(不稳定地(忽略它。(谨慎使用,就像所有涉及dynamic的东西一样。此外,分析器可能会警告"不必要的上抛"。(

最新更新