|
|
デリゲートとは |
|
デリゲートとは、メソッドを新たに実装しなくても、他の場所で実装されているメソッドに処理を委譲して実行することができる一連の機能の事を言います。もちろん、デリゲートを使用しなくても、直接そのクラスのメソッドを呼び出して使用することもできますが、状況に応じて呼び出すメソッドを変更したい場合、デリゲートに違うメソッドを指定するだけで異なった振る舞いを行えるのがデリゲートの一番の特徴です。
デリゲートの使い方は少々変わっており、変数にメソッドを代入するような記述をします。
1
2
3 |
修飾子 delegate 戻り値型 デリゲート名(引数1, 引数2, 引数3); //デリゲートの宣言
デリゲート名 変数名 //delegate型の変数を宣言
デリゲート型変数 = メソッド名; //メソッドを代入 |
1行目では、代入するメソッドのシグネチャ(戻り値、引数)を定義します。ここで宣言したシグネチャ以外のメソッドは代入することができません。2行目ではdelegate型の変数を宣言し、3行目でdelegate型の変数にメソッドを代入しています。ここではメソッドのシグネチャを記入する必要はなく、メソッド名のみで構いません。また、2行目と3行目は以下のほうに一行にまとめることもできます。
1 |
デリゲート名 変数名 = メソッド名()//delegate型の変数を宣言と代入を同時に行う |
なお、デリゲート型の変数に代入したメソッドは通常のメソッドの呼び出しと同じように使用します。
1
2
3 |
変数名(); //戻り値、引数共に指定されていない場合
変数 = 変数名(); //戻り値が指定されている場合
変数 = 変数名(引数1. 引数2, 引数3...); //戻り値、引数共に指定されている場合 |
以下のプログラムは、デリゲートを使用して処理を委譲したプログラムの例です。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 |
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
delegate void delegateMethod();
class Program
{
static void Main(string[] args)
{
delegateMethod handler;
handler = Class.message;
handler();
Console.ReadLine();
}
}
class Class
{
static public void message()
{
Console.WriteLine("Class.methodが実行されました");
}
}
} |
実行結果
8行目では、戻り値、引数ともに指定しないデリゲート「delegateMethod」を宣言しています。13行目では「delegateMethod」型の変数「handler」を宣言し、次の行で「Class」クラスの静的メソッド、「message」を代入しています。15行目では「handler」を呼び出して、代入したメソッド「message」に処理を委譲させています。実行結果を見てみると、Programクラスでは定義していない「message」メソッドが実際に使用できていることがわかります。
デリゲートを使用する際、デリゲートの宣言を行う場所に注意してください。デリゲートの宣言はクラスの外側で行う必要があります。また、今回は静的なメソッドをデリゲートに代入させましたが、インスタンスメソッドを代入する事もできます。その際は、メソッドを使用するためにインスタンス化が必要になりますので注意してください。
|
|
デリゲートの具体的なコーディング例 |
|
先程のプログラムでは、静的メソッドに処理を委譲させていましたが、インスタンスメソッドに処理を委譲しているプログラムを以下に示します。今回は、もっと具体的な例として連絡先を取り扱うプログラムを実装し、状況に応じて委譲先を変えるようコーディングします。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
delegate void delegateMethod(string str1, string str2, string str3);
class Program
{
static void Main(string[] args)
{
Adress obj = new Adress();
delegateMethod handler;
handler = obj.once;
handler("Europaris","xxx-xxxx-xxxx","europaris@xxx.xx.xx");
handler = obj.list;
handler("Europaris","xxx-xxxx-xxxx","europaris@xxx.xx.xx");
Console.ReadLine();
}
}
class Adress
{
public void once(string str1, string str2, string str3)
{
Console.WriteLine("------------アドレス情報------------");
Console.WriteLine(
String.Format("名前:{0}\n電話番号:{1}\nメールアドレス:{2}"
, str1, str2, str3));
}
public void list(string str1, string str2, string str3)
{
Console.WriteLine("------------リスト表示------------");
Console.WriteLine(
String.Format("名前:{0}, 電話番号:{1}, メールアドレス:{2}"
, str1, str2, str3));
}
}
} |
実行結果
1
2
3
4
5
6 |
------------アドレス情報------------
名前:Europaris
電話番号:xxx-xxxx-xxxx
メールアドレス:europaris@xxx.xx.xx
------------リスト表示------------
名前:Europaris, 電話番号:xxx-xxxx-xxxx,
メールアドレス:europaris@xxx.xx.xx |
このプログラムでは、8行目で引数を3つ指定するデリゲートを宣言しています。今回は、状況に応じて「Adress」クラスのメンバである24行目の「once」メソッド、31行目の「list」メソッドに処理を委譲させます。「once」メソッドは、引数として指定した連絡先の情報を改行を含めたフォーマットで表示するメソッドで、「list」メソッドは連絡先をリスト表示するメソッドとして実装しています。
これらのメソッドはインスタンスメソッドなので、まず始めに14行目で「Adress」クラスをインスタンス化しています。次の行ではデリゲート型の変数「handler」を宣言し、「obj」インスタンスが保持する「once」メソッドを代入しています。15行目では「handler」に必要な引数を渡し、実際に処理を委譲させてコンソール画面に文字列を出力させました。
17行目以降では委譲するメソッドを「list」に変更し、同じように「handler」を呼び出して処理を委譲させています。出力結果では委譲先が違うため、処理の実行内容が異なっていることがわかります。
このように、柔軟性を考えるとデリゲートはとても便利です。ただし、この2つのメソッドしか呼び出さない事がわかっているのであれば、わざわざデリゲートを実装しなくても構いません。デリゲートは、今後新たなフォーマットで出力しなければならないケースが発生した場合に、委譲するメソッドを変更するだけで良いところにメリットがあります。
|
|
複数のメソッドに処理を委譲させる |
|
デリゲートはもうひとつの大きな特徴として、複数のメソッドに対して同時に処理を委譲させることができます。結果として、複数の処理をボックス化して、一回の呼び出しで様々な処理を実現できます。
以下のプログラムは、ひとつのデリゲート型変数に複数のメソッドを代入して実行するプログラムを実現した例です。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
delegate void delegateMethod();
class Program
{
static void Main(string[] args)
{
delegateMethod handler;
handler = Class.show1;
handler += Class.show2;
handler();
Console.ReadLine();
}
}
class Class
{
static public void show1()
{
Console.WriteLine("ひとつ目のメソッドが呼ばれました");
}
static public void show2()
{
Console.WriteLine("ふたつ目のメソッドが呼ばれました");
}
}
} |
実行結果
1
2
|
ひとつ目のメソッドが呼ばれました
ふたつ目のメソッドが呼ばれました |
このプログラムを見てみると、14行目では通常通りデリゲートにメソッドを代入しているのに対し、15行目では複合代入演算子を使用して同じデリゲート型変数にメソッドを代入させています。複合代入演算子を使用すれば、いくつでもメソッドを格納することが可能です。なお、代入したメソッドを削除したい場合は「-= 削除したいメソッド名」と記述することで、任意のメソッドを削除できます。
以後デリゲート型変数である「handler」を呼び出せば、複数のメソッドを呼び出すことが可能になります。このように、デリゲートは複数のメソッドをひとつにまとめるときにも使用できます。
|