Effective C# 3rd 読書メモ 24 ベースクラス・インターフェイスを使ってジェネリックの特殊化をしない

ジェネリックメソッドを定義する際には、オーバーロードの扱いに注意が必要である。

ジェネリックメソッドは、ベースクラスがマッチするメソッドよりも優先度が高い。以下の2つのメソッドがある場合に呼び出されるオーバーロードは以下の通り。

void WriteMessage(MyBase b)
{
}

void WriteMessage<T>(T obj)
{
}
  • パラメータがMyBaseオブジェクト => WriteMessage(MyBase)
  • パラメータがMyBaseの派生クラスのオブジェクト => WriteMessage(T)

このルールはインターフェイスにも同様に適用される。

一般に、あるクラスとその子孫全てをサポートするために、ベースクラスに対してジェネリックの特殊化を行うことは、良い考えではない。インターフェイスも同様である。

以下のようにメソッド内で型をチェックして処理を分けることもできるが、最適な方法ではない。

// 注意: 最適な方法ではない
void WriteMessage<T>(T obj)
{
    if (obj is MyBase)
        WriteMessage(obj as MyBase);
    else if (obj is IMessageWriter)
        WriteMessage((IMessageWriter)obj);
    else
        WriteLine(obj.ToString());
}

この実装には実行時のオーバーヘッドが発生するという問題があるため、このような特殊化は 明らかにより良い機能を提供できる場合 かつ パフォーマンス上の悪影響が無視できる程度である場合 にのみ行うべきである。

コメントを残す

コメントを残す