同一シグネチャのインスタンスメソッドの呼び出し一般に、元のクラスに変化を加えること無くメソッドを追加したい場合、派生クラスを作成してそのクラスでメソッドを追加することになります。methods)を使うと、元の型への変更をせず、かつ直接継承関係にない型からメソッドを追加することができます。追加といっても実際に型に対してメソッドが追加されるのではなく、型の外部で宣言された静的メソッドを、あたかもインスタンスメソッドのように呼び出すことができるようにするのが拡張メソッドです。拡張メソッドを宣言すると、見かけ上は型にメソッドが追加されたように見えます。(VB)例えば次のような静的メソッドがあったとします。これを拡張メソッドにすると、あたかもインスタンスメソッドであるかのように呼び出すことができます。2.このように、拡張メソッドを用いると既存の型に一切変更を加えずにメソッドを追加できます。拡張メソッドとして宣言すると、静的メソッドをインスタンスメソッドのように呼び出すことができます。拡張メソッドは、値型など継承することができない型に対してもメソッドを追加することができます。拡張メソッドを使った代表的な例にLINQがあります。System.Linq名前空間をインポートすることにより、LINQの拡張メソッドが使えるようになります。次の例で使用しているAverageメソッドはIEnumerable<T>インターフェイスに対して追加される拡張メソッドです。2.実行結果2.5このAverageメソッドは本来IEnumerable<T>やList<T>クラスには存在しないものですが、List<T>クラスに追加されたメソッドのように使用することができます。拡張メソッドはインスタンスメソッドのように呼び出せる点をのぞくと、実体は単なる静的メソッドです。上記のAverageメソッドも実際にはEnumerableクラスで定義されている静的メソッドです。このため、次のように静的メソッドとして呼び出すこともできます。2.拡張メソッドの宣言クラスライブラリで提供されるもの以外にも、拡張メソッドを独自に宣言して追加することもできます。拡張メソッドは、静的メソッドを宣言するときとさほど変わらない方法によって宣言することができます。C#では、メソッドの第一引数にthisキーワードを前置すると、その引数の型に対する拡張メソッドとして公開することができます。valという引数を記述するとstring型に対する拡張メソッドとなります。VBには拡張メソッドを宣言する専用のキーワードは用意されておらず、メソッドにExtension属性(System.Runtime.CompilerServices名前空間)を付与することで拡張メソッドを宣言します。class、VBではモジュール)で宣言する必要があります。引数でメソッドを追加する型を定めるため、拡張メソッドは必然的に引数が一つ以上のメソッドとなります。2.thisキーワードを使って宣言した拡張メソッドには、コンパイル時に自動的にExtension属性が付与されます。4以前の場合、Extension属性はSystem.Core.dllで宣言されているため、System.Core.dllを参照に追加する必要があります。C#では、VBのようにExtension属性を指定することによって拡張メソッドを実装することはできません。次のようにコンパイルエラーとなります。使用しないでください。キーワードを使用してください。2.引数のある拡張メソッド拡張メソッドの場合もほかのメソッドと同様に引数を渡すことができます。引数には拡張メソッドの呼び出しを行ったインスタンス、第二引数以降には拡張メソッドの呼び出しに指定された引数が渡されます。2.実行結果DEADBEAFdeadbeafインターフェイス・列挙体の拡張メソッド拡張メソッドはクラス・構造体のほか、インターフェイスや列挙体に対しても追加することができます。次の例では、列挙体に拡張メソッドを持たせるようにしています。2.実行結果TrueFalseTrueこの例の場合、IsReadOnlyはメソッドではなくプロパティとする場合が多いですが、既存の型にプロパティを追加する拡張プロパティのような機能はなく、またそういったプロパティを宣言することもできないため、拡張メソッドとして宣言しています。LINQはインターフェイスへ拡張メソッドを追加する最たる例です。LINQでは、IEnumerable<T>インターフェイスに追加される拡張メソッドがEnumerableクラスで多数宣言されています。2.LINQの拡張メソッドがどのように実装され、機能するかについてはLINQ:実装して理解するで解説しています。拡張メソッドを宣言するクラスには任意の名前を使用することができます。拡張メソッドを追加する型と関連する名前となっている必要はありませんが、拡張メソッドを含むクラスであることをわかりやすくするためにXxxExtension(s)というクラス名(string型に対する拡張メソッドを追加するクラスならStringExtensionなど)にすることが多いようです。名前空間のインポート異なる名前空間の型で宣言されている拡張メソッドを使用する場合は、その名前空間をインポートしておく必要があります。クラス・構造体など他の型と同様、インポートされていない名前空間で宣言されている拡張メソッドを参照しようとしても、名前を解決できずコンパイルエラーとなります。2.null変数からの呼び出し拡張メソッドはnull/Nothingが代入されている変数からも呼び出すことができます。見かけ上はヌル参照となるように見えますが、実際のところこれは引数にnull/Nothingを指定して静的メソッドを呼び出すことと変わらないため、実行時エラーとはなりません。見かけ上、拡張メソッドはインスタンスメソッドですが、実体はあくまで別のクラスで宣言された静的メソッドであるため、privateやprotectedなど外部に公開されていないインスタンスメンバを拡張メソッド内から参照したり呼び出したりすることはできません。通常のメソッドの場合と同様、拡張メソッド内でアクセスできるのは外部に公開されているメンバのみです。アクセスできない保護レベルになっています。あるため、このコンテキストではアクセスできません。2.同一シグネチャのインスタンスメソッドの呼び出し拡張メソッドと同名で同じシグネチャ(引数リスト)のインスタンスメソッドがすでに型に存在している場合は、型に存在するメソッドの呼び出しが優先されます。同名のメソッドが存在する場合でも、拡張メソッドとしてではなく静的メソッドとして呼び出すことはできます。