a ?? b
表达式需要找出表示两个可能的结果值的单个类型,一个是类型A
,另一个是类型B?
.
它不判断A
和B?
是否都可以赋值给I?
,而是try 找出a ?? b
结果的类型,作为组合了A
和B?
的单个类型,这意味着同时找到A
和B
的超类型.
为此,它使用语言指定的"最小上界"算法计算上界.(我引用这个名字,因为它找到了an的上限,这有时是最小的上限,但并不总是.)
这两种类型是:
A
和直接超类型I
和M
,这两个类型都具有立即超类型Object
,它具有超类型Object?
(和所有其他顶级类型).
B?
具有超型I?
、M?
及其超型Object?
.
这里的问题是,虽然它可以看到I
和I?
出现在这些类型中,因此它可以确定I?
是上限,
它还找到M
和M?
并确定M?
是上界,
而这两种类型在其他方面是完全等价的,它们具有相同长度的超级链,最高可达Object
,并且彼此不相关.least的上限也不是.因此,该算法忽略它们,并寻找既共享又没有另一种相同类型的"深度从Object
开始"的内容.它找到了Object?
个.
它不能赋值给I
.
这是DART中最小上界算法的一个已知缺点(在几个中),但这是一个很难以最佳方式解决的问题,因为对于一个类来说,引入一些内部私有超类非常容易,有时会引入两个公共子类的类型then becomes the least upper bound,这让用户摸不着头脑.
有requests个可以做得更好,例如,通过不忽略上下文类型,但更改类型推断必须非常小心地完成.它可以 destruct 已针对当前行为进行微调的现有代码.
这里没有很好的变通方法,但有一些实用的变通方法.
您必须重写代码以确保两个分支的静态类型中都不包含不必要的M
类型.
我没有将结果向下强制转换为I?
(这需要运行时类型判断),而是向上强制转换原始值:
final I? i3 = a ?? (b as I?); // ignore: unnecessary_cast
这应该是完全自由的向上投射,但可能(将!)导致分析器警告,您将不得不忽略.