跳到主內容

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 不具有函式所需的型別時,它才會丟擲異常。這比原始版本更好,因為它不會因為靜態型別不匹配而丟擲。它僅在出於健全性原因必須丟擲時丟擲。