C# のデリゲートとイベントの概要
デリゲートは、.NET における "遅延バインディング" のメカニズムです。 遅延バインディングとは、皆さんが作成するアルゴリズムについて、その一部を実装するメソッドを呼び出し元からも少なくとも 1 つ与えることを意味します。
たとえば天文学アプリケーションで、一連の星を並べ替えることを考えてみましょう。 星の並べ替え基準には、地球からの距離や星の等級、知覚的な明るさを選ぶことができます。
いずれの場合も、Sort() メソッドが行うことは基本的に同じです。つまり何らかの比較に基づいて一連の項目を整列します。 しかし、2 つの星を比較するコードは、並べ替えの基準によって異なります。
ソフトウェアには、この種の手法が半世紀にわたって使用されてきました。 C# 言語のデリゲートの概念は、きわめて優れた言語機能と、その概念を中心にしたタイプ セーフ機能を実現します。
本シリーズの中で後述しているように、このようなアルゴリズム向けに記述された C# コードはタイプ セーフです。 コンパイラにより、引数と戻り値の型が一致することが保証されます。
関数ポインターでは、呼び出し規則をより細かく制御する必要がある同様のシナリオがサポートされています。 デリゲートに関連付けられたコードは、デリゲート型に追加された仮想メソッドを使用して呼び出されます。 関数ポインターを使用して、さまざまな規則を指定できます。
デリゲートの言語上の設計目標
最終的にデリゲートとなる機能を実現するにあたって、言語の設計者たちはさまざまな目標を設定しました。
設計チームが目指したのは、あらゆる遅延バインディング アルゴリズムに適用できる共通の言語概念です。 デリゲートによって、開発者が 1 つの概念を身に付け、ソフトウェアに関するさまざまな課題にその知識を応用できるような言語の実現を目標に掲げたのです。
次に設計チームが目指したのは、シングルキャストとマルチキャストの両方のメソッド呼び出しをサポートすることでした。 (マルチキャスト デリゲートは、複数のメソッド呼び出しを連結するデリゲートです。実際の例については、本シリーズの中で後述しています。)
設計チームは、C# のあらゆるコード要素に関して開発者たちが当然と考えるレベルのタイプ セーフティをデリゲートにおいても実現したいと考えていたのです。
また、設計チームは、デリゲートを初めとする遅延バインディング アルゴリズムの利便性が発揮される具体的なパターンは、イベント パターンであると認識していました。 .NET のイベントの基本的なパターンをデリゲートのコードで確実に実現したいと考えていたのです。
そうした目標に向けたすべての作業の成果として C# と .NET にサポートされたのが、デリゲートとイベントです。
以降このシリーズの記事では、言語の機能やライブラリのサポート、デリゲートとイベントを扱う際に用いられる一般的な用語について取り上げています。 以下について説明します。
delegate
キーワードとそれによって生成されるコード。System.Delegate
クラスの機能とその使い方。- タイプ セーフなデリゲートの作成方法。
- デリゲート経由で呼び出すことのできるメソッドの作成方法。
- ラムダ式を使ったデリゲートやイベントの扱い方。
- LINQ の構成要素としてデリゲートがどのように使われているか。
- .NET のイベント パターンの基礎としてデリゲートがどのように使われ、両者がどのように違うのか。
では、始めましょう。
.NET