unsafe_variance
不安全类型:在非协变位置具有类型变量。
详情
#实例变量的类型在其非协变位置包含封闭类、混入或枚举的类型参数,则很可能由于类型检查失败而导致运行时故障。例如,在 class C<X> {...}
中,void Function(X) myVariable;
形式的实例变量可能会导致此类运行时故障。
对于 getter 或方法,如果其返回类型在其封闭声明的类型参数中具有非协变出现,则情况也是如此。
此 lint 标记此类成员声明。
错误示例
class C<X> {
final bool Function(X) fun; // LINT
C(this.fun);
}
void main() {
C<num> c = C<int>((i) => i.isEven);
c.fun(10); // Throws.
}
问题在于 X
在 fun
类型的参数类型中出现。
减少运行时类型错误可能性的方法之一是确保非协变成员 fun
仅 在 this
上使用。我们无法严格强制执行此操作,但我们可以将其设为私有并添加转发方法 fun
,以便我们可以在同一库中本地检查是否满足此约束
较好示例
class C<X> {
// ignore: unsafe_variance
final bool Function(X) _fun;
bool fun(X x) => _fun(x);
C(this._fun);
}
void main() {
C<num> c = C<int>((i) => i.isEven);
c.fun(10); // Succeeds.
}
完全安全的方法需要 Dart 尚未具备的功能,即静态检查的变体。有了它,我们可以指定类型参数 X
是不变的(inout X
)。
在没有静态检查的变体支持的情况下,可以模拟不变性。这会对子类型的创建施加一些限制,但忠实地提供了 inout
将给出的类型
良好示例
typedef Inv<X> = X Function(X);
typedef C<X> = _C<X, Inv<X>>;
class _C<X, Invariance extends Inv<X>> {
// ignore: unsafe_variance
final bool Function(X) fun; // Safe!
_C(this.fun);
}
void main() {
C<int> c = C<int>((i) => i.isEven);
c.fun(10); // Succeeds.
}
使用这种方法,C<int>
不是 C<num>
的子类型,因此 c
必须具有不同的声明类型。
另一种可能性是将变量声明为具有安全但更通用的类型。这样使用变量本身是安全的,但每次调用都必须在运行时检查
诚实示例
class C<X> {
final bool Function(Never) fun;
C(this.fun);
}
void main() {
C<num> c = C<int>((int i) => i.isEven);
var cfun = c.fun; // Local variable, enables promotion.
if (cfun is bool Function(int)) cfun(10); // Succeeds.
if (cfun is bool Function(bool)) cfun(true); // Not called.
}
启用
#要启用 unsafe_variance
规则,请在您的 analysis_options.yaml
文件中的 linter > rules 下添加 unsafe_variance
linter:
rules:
- unsafe_variance
如果您改为使用 YAML 映射语法来配置 linter 规则,请在 linter > rules 下添加 unsafe_variance: true
linter:
rules:
unsafe_variance: true
除非另有说明,否则本网站上的文档反映的是 Dart 3.7.1 版本。页面上次更新于 2025-03-07。 查看源代码 或 报告问题。