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

Chapter14 拡張メソッド

川俣 晶
2010/03/01

14.10 thisの正体

 拡張メソッドを宣言する際には「thisキーワード」を使うが、これはインスタンスのメソッドが自分自身を指し示すために使うthisキーワードと同じ名前である。これは、異なる役割に同じキーワードを割り当てているのではなく、役割が同じであるから同じキーワードを割り当てているのである。

 リスト14.12は、通常のメソッドと拡張メソッドで同じ機能を記述した例である。これで、thisキーワードが付加されたパラメータ(this B t)と「this.Number」のthisがまったく同じように使われていることがわかるだろう。

using System;
using X;

namespace X
{
  public static class A
  {
    public static void AddByExtension(this B t, int n)
    {
      t.Number += n; // ここに注目!
    }
  }
  public class B
  {
    public int Number { get; set; }
    public void AddByClassMethod(int n)
    {
      this.Number += n; // ここに注目!
    }
  }
  class Program
  {
    static void Main(string[] args)
    {
      var b = new B() { Number = 0 };
      b.AddByExtension(2);
      b.AddByClassMethod(3);
      Console.WriteLine(b.Number);
    }
  }
}
リスト14.12 thisパラメータとインスタンス参照のthisの役割は同じ

 このような、明示的にthisを渡すスタイルは、「実はコンパイラの内部実装を明示的に書き直したもの」と見なすこともできる。

 たとえば、インスタンスやthisという概念がないC言語の関数と、それらの概念があるC++言語のインスタンスメソッドのマシン語レベルにおける実装面での機能差は、主にthisという概念の有無に求められる。そして、thisとは具体的には「暗黙的に追加されるもう1つのパラメータ」として実装することができる(最近のC++コンパイラはもっと効率的な実装を行っているようであり、この説明に当てはまらない)。そのため、C++言語処理系の中には、インスタンスメソッドを、thisポインタを引数に追加した関数として呼び出せるものがあったように記憶する(かなり強引に行う必要があり、あたりまえに記述してもできないが)。

 このような背景から考えると、拡張メソッドとは本来「暗黙的に渡されるはずのthisを明示的に引き渡すように宣言されたメソッド」と見ることもできる。

 ちなみに、静的なメソッドはthisを持たない。そのため、C++の静的なメソッドとC言語の関数は、(いくつかの小さな相違点を除き)同じと見なせる。そのため、C言語の関数ポインタを渡すWindows APIには、C++のインスタンスメソッドは渡せないが、静的なメソッドなら渡せることがある。

 このような「thisを持たない」という性質は、C#の静的クラス、静的メソッドにも共通する。thisを明示的に受け取る拡張メソッドが、静的クラスかつ静的メソッドでなければならない理由はここにある。thisを明示的に受け取る以上、暗黙的に受け取るthisがあるとトラブルのもとになる。


 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 記事ランキング

本日 月間