Effective C# 3rd 読書メモ 22 ジェネリックの共変性と反変性をサポートする

共変性(covariance)と反変性(contravariance)は、ある型が別の型に変換可能な性質をもっている、ということを意味する。可能なときはいつでも、ジェネリックなインターフェイスを装飾して、ジェネリックの共変性と反変性をサポートできるようにすべきである。

  • 共変性: 継承関係において、より上方の型に変換可能である
  • 反変性: 継承関係において、より下方の型に型に変換可能である

C# 4.0より前では、全てのジェネリック型は不変(invariant)だった。C# 4.0以降では、新しいキーワードを使うことで、共変性と反変性をサポートすることができる。

パラメータにout修飾子をつけると、 (1) メソッドの戻り値 (2) プロパティのgetアクセサ にしか使えなくなる。out修飾子による制限のため、Tの内容は変更されることがないため、より上方の型への変換は安全に行うことができる。

以下は、out修飾子を使用しているIEnumerator<T>の例である。

public interface IEnumerator<out T> : IDisposable, IEnumerator
{
    new T Current { get; }
}

以下のように、Enumerator<T>には共変性がある(ベース型に変換できる)。

Enumerator<string> strEnum = new Enumerator<string>();
Enumerator<object> objEnum = strEnum;

逆に、in修飾子を使うことで、メソッドのパラメータにしか使えないように制限することができる。

public interface IComparer<in T>
{
    int Compare(T a, T b);
}

以下のように、Comparer<T>には反変性がある(派生型に変換できる)。

IComparer<object> objComp = new Comparer<object>();
IComparer<string> strComp = objComp;

参考:ジェネリックの共変性と反変性

コメントをどうぞ

コメントを残す