連載:[完全版]究極のC#プログラミング

Chapter14 拡張メソッド

川俣 晶
2010/03/01

14.3 拡張メソッドの概要

 拡張メソッドは、すでに存在するクラスに対して、そのクラスを変更することなく、メソッドを追加できる機能である。

 まず、最もシンプルな例を見てみよう。

 次のリスト14.5は、名前空間YにあるクラスAを変更することなく、メソッドMyMethodを追加するものである。

using System;
using X;

namespace X
{
  static class B
  {
    // 拡張メソッド
    public static void MyMethod(this Y.A a)
    {
      Console.WriteLine("MyMethod called");
    }
  }
}

namespace Y
{
  class A
  {
  }
  class Program
  {
    static void Main(string[] args)
    {
      var a = new A();
      a.MyMethod(); // 出力:MyMethod called
    }
  }
}
リスト14.5 最も単純な拡張メソッドの使用例

 このサンプルコードで、名前空間Yにはなんら特別な構文は存在しない。ここで注目すべきは、名前空間X内のコードと「using X;」の2つである。

 拡張メソッドは、次の条件を満たすメソッドを記述することで作成できる。

  • 静的なメソッド(static)である
  • 静的クラス(static)に記述されている
  • 第1パラメータの先頭にthisキーワードが前置されている
  • 第1パラメータの型がメソッドを追加すべき型である

 これで、このメソッドは、あたかも「第1パラメータの型」のメソッドであるかのように呼び出すことができる。「a.MyMethod();」というメソッド呼び出しがそれである。

 ところで、「名前空間Yにはなんら特別な構文は存在しない」と書いたが、それは厳密には正しくない。「a.MyMethod();」という呼び出しは、実は拡張メソッドを呼び出す専用構文なのである。一見、なんら特別な構文には見えないかもしれないが、本来このメソッドが受け取るはずの第1パラメータに引数を渡していない点に注意を払っていただきたい。つまり、本来存在する引数を自動的に補って呼び出しを行うという特別な構文なのである。

 では、第1引数はどうやって補われるのだろうか? それは使用されたインスタンスそのものである。「a.MyMethod();」であれば、「a」が第1引数に補われる。したがって、リスト14.5においては、以下の2つのメソッド呼び出しは実質的に同じ機能性を持つ。

a.MyMethod();

B.MyMethod(a);

 さて、最後の注目すべき点は「using X;」である。拡張メソッドは、拡張メソッド自身を含む名前空間をusing文で指定しない限り有効にならない。つまり、定義しただけでは使用できず、スイッチを入れなければならない。これを「拡張メソッドをインポートする」という。実際、リスト14.5で「using X;」をコメントアウトすると、次のようなコンパイルエラーが発生する。

エラー 1 'Y.A' に 'MyMethod' の定義が含まれておらず、型 'Y.A' の最初の引数を受け付ける拡張メソッドが見つかりませんでした。using ディレクティブまたはアセンブリ参照が不足しています。
リスト14.5で「using X;」をコメントアウトすると発生するコンパイルエラー


 INDEX
  [完全版]究極のC#プログラミング
  Chapter14 拡張メソッド
    1.14.1 C# 2.0プログラマーの悲劇
    2.14.2 Allメソッドを利用するのに必要な記述
  3.14.3 拡張メソッドの概要
    4.14.4 スイッチなしで機能する例
    5.14.5 sealedクラスを拡張する
    6.14.6 拡張メソッドはオブジェクト内部に手出しできない
    7.14.7 拡張メソッドはオブジェクトの振る舞いを変更できない
    8.14.8 拡張メソッドが安全である理由
    9.14.9 メソッド呼び出しと型の関係
    10.14.10 thisの正体
    11.14.11 拡張メソッドを使用すべきとき
    12.14.12 コレクションに拡張されるメソッド
    13.14.13 なぜ「using System.Linq;」なのか?/練習問題
 
インデックス・ページヘ  「[完全版]究極のC#プログラミング」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間