拡張メソッドは対象とする型の提供者以外は作成するべきではありません

非常に魅惑的な拡張メソッドですが、そのリスクについてはあまり語られていないように思えたので(百も承知だから誰も書いてないだけかもしれません) 、書いてみます。拡張メソッドとは、C#3.0、VB9.0で取り入れられた言語の機能で、詳細は下記のリンクを参照してください。

拡張メソッド (C# プログラミング ガイド)
拡張メソッド (Visual Basic)

端的に言うと、拡張メソッドだよと印を付けた静的メソッド/共有メソッドは、その静的メソッド/共有メソッドの第一引数に指定した型のインスタンスメソッドのように振舞う、という機能です。あまり意味のある使い方ではないですが、C#VBでの使用例を以下に示します。

using System;

class Program
{
    static void Main(string[] args)
    {
        "あいう".Print();
    }
}

static class StringExtenstions
{
    public static void Print(this string target)
    {
        Console.WriteLine(target);
    }
}
Imports System.Runtime.CompilerServices

Module Program
    Sub Main()
        Dim s As String = "あいう"
        s.Print()
    End Sub
End Module

<Extension()>  _
Module StringExtenstions
    <Extension()> _
        Sub Print(ByVal target As String)
            Console.WriteLine(target)
    End Sub
End Module

拡張メソッドは非常にわくわくする機能ですが、同時に危険な香りがぷんぷんします。上記のURLにはそのリスクについても記載がありますが、私なりにまとめると以下のようになります。

○あなたが拡張メソッドを作成した場合のリスク


サードパーティのクラスライブラリ提供者が拡張メソッドを提供した場合のリスク

  • A社の拡張メソッドとB社の拡張メソッドのシグネチャが同じだったら、どちらの拡張メソッドも使用できません。
    • 名前空間が別であれば、片方だけをインポートすることは可能。
  • A社がインタフェースA向けの拡張メソッドを用意し、B社がインタフェースB向けの拡張メソッドを用意した場合、対象となる型(インタフェースAとインタフェースB)以外がまったく同じシグネチャだった場合、インタフェースAとインタフェースBを実装したクラスCに対してはこれらの拡張メソッドはどちらも使用できません。
    • →IEnumerable(T)向けのメソッドXとIList(T)向けのメソッドXが定義されていたらどうでしょうか?

○拡張メソッド全体のリスク

  • 上位のクラス(例えば、極端に言えばObjectクラス)に拡張メソッドを提供した場合、ありとあらゆる派生クラスにその拡張メソッドが存在することになります。派生クラスで同じシグネチャのメソッドを定義した場合、その定義したインスタンスメソッドが有効になるため動作上の問題はありませんが、間違いなく混乱のもとになります。(後、瑣末な話ですが、VisualStudioを使っている場合、常にインテリセンスにその拡張メソッドが表示されて、結構うっとおしいです。)


○拡張メソッドを提供してもよいパターン

  • 自分が作成したインタフェース、列挙型などインスタンスメソッドを提供できない型に対する拡張メソッド
    • →(例) Microsoft社のIEnumerable(T)に対するMicrosoft社による拡張メソッドの提供
  • 自分の汎用的でないプロジェクトに限定して使う場合で、使用しているクラスライブラリ等の今後のバージョンアップの場合に発生するリスクを見越してOKがだせる場合でしょう。


○既存の型のために拡張メソッドを用意したいと思ったら・・・

  • ぜひその型を提供しているベンダーに××なメソッドが欲しい!と要望を出してみるのがよいと思います。可能であれば拡張メソッドを作成するのではなく、その型のインスタンスメソッドを作るべきであり、拡張メソッドを作成するにしても、その型の提供者でなければ、今後のバージョンアップを見据えて安全に拡張メソッドを提供することはできないからです。


いろいろ悪い使い方を考えて見ると楽しいと思いますが、あくまで実験に留めておいてくださいね。お仕事ではあまり使えないなぁというのが個人的な印象です。趣味のプログラミングではがんがん使ってます(笑) すごく便利です。