在Dart中使用“as”进行类型转换

3
为什么传递一个 D2 的实例而不是将 d1 设置为 null,会导致在 Foo 中出现错误?在 .NET 中建议使用 as 而不是 is,因为 is 通常需要进行两次转换/转型,这比使用 null 测试更加昂贵。
class Base {}
class D1 extends Base{}
class D2 extends Base{}

void Foo(Base d1OrD2) {
  var d1 = d1OrD2 as D1;
  if (d1 != null) print("it's d1");
  else {
    var d2 = d1OrD2 as D2;
    if (d2 != null) print("it's d2");
  }
}


void main() async{
  Foo(D2()); // throws exception D2 is not an instance of D1.
  Foo(D1()); // works
}

这里的“break”具体是什么意思? - Günter Zöchbauer
1
@GünterZöchbauer修改了问题以使其更加清晰。 - dragonfly02
1个回答

10

在Dart中,as运算符会抛出异常,如果对象不是右侧类型的实例(或者为null)。这与C#中的as运算符并不相似,后者会返回null而不是抛出异常。

你的代码以var d1 = d1OrD2 as D1;开始,当d1OrD2是一个D2实例时,该操作会抛出异常。

你应该改为:

void Foo(Base d1OrD2) {
  if (d1OrD2 is D1) {
    // Static type of d1OrD2 is D1 here, you can call D1 methods on it.
    print("it's d1");
  } else {
    var d2 = d1OrD2 as D2;
    print("it's d2");
  }
}

在Dart中,一旦您使用“is”来测试类型并返回“true”,被测试的实例就会自动转换为已测试的类型?换句话说,在Dart中最好使用“is”而不是“as”? - dragonfly02
没有进行任何转换。只是静态分析可以推断出在运行时,只有当类型为“D1”时才能到达该分支,并且自动完成会显示正确的建议。如果“d10rD2”是一个getter,据我所记得,这将不再起作用,因为getter可能会在后续访问中返回不同的值。只是为了证明这不能广泛应用。 - Günter Zöchbauer
正确。在某些情况下,像x is D1这样的测试将会将变量 x 的类型提升为 D1。这需要x是一个本地变量,其类型是D1的超类型,而不是dynamic,并且在受到测试保护的代码中没有对x进行赋值。 - lrn

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接