跳到主内容

unsafe_variance

此类型不安全:类型参数出现在了非协变位置。

描述

#

当实例成员的结果类型在其包含声明的类型参数中是逆变或不变时,分析器会生成此诊断。变量的结果类型即为其类型,getter 或方法的结果类型即为其返回类型。此 lint 会对此类成员发出警告,因为它们可能导致运行时类型检查失败,且在调用处没有静态警告或错误。

示例

#

以下代码会生成此诊断,因为 X 作为参数类型出现在 f 的类型中,这是一种此类型参数的逆变出现。

dart
class C<X> {
  bool Function(X) f;
  C(this.f);
}

这是不安全的:如果 c 具有静态类型 C<num> 和运行时类型 C<int>,则 c.f 将会抛出异常。因此,即使 a 作为 c.f 的参数具有正确的类型,每次调用 c.f(a) 也会抛出异常。

常见修复方法

#

如果受 lint 影响的成员是或可以是私有的,则您可以强制它仅在 this 以外的接收者上访问。这足以确保不会发生运行时类型错误。例如

dart
class C<X> {
  // NB: Ensure manually that `_f` is only accessed on `this`.
  // ignore: unsafe_variance
  bool Function(X) _f;

  C(this._f);

  // We can write a forwarding method to allow clients to call `_f`.
  bool f(X x) => _f(x);
}

通过为受 lint 影响的成员使用更通用的类型,可以消除不安全变异性。在这种情况下,您可能需要在调用处检查运行时类型并执行向下转型。

dart
class C<X> {
  bool Function(Never) f;
  C(this.f);
}

如果 c 具有静态类型 C<num>,则可以测试其类型。例如,c.f is bool Function(num)。如果它具有该类型,则可以安全地使用类型为 num 的参数调用它。

通过使用更通用的类型(例如 Function,它本质上是函数的 dynamic 类型),也可以消除不安全变异性。

dart
class C<X> {
  Function f;
  C(this.f);
}

这将使 c.f(a) 动态安全:当且仅当参数 a 不具有函数所需的类型时,它才会抛出异常。这比原始版本更好,因为它不会因为静态类型不匹配而抛出。它仅在出于健全性原因必须抛出时抛出。