戻り値と引数が合えば委譲できる
delegateは、対象となるメソッドにprivateキーワードなどが付加されてアクセス権が与えられていない場合などを除き、戻り値と引数が合えば委譲できる。別クラスの異なる名前のメソッドであっても、戻り値と引数だけ合っていれば委譲できる。以下は、まったく無関係な別クラスの異なる名前のメソッドに委譲した例である。
1: using System;
2:
3: namespace ConsoleApplication24
4: {
5: delegate void Sample( int x, int y );
6: class Class2
7: {
8: public int result;
9: public void methodMult( int x, int y )
10: {
11: result = x * y;
12: }
13: }
14: class Class3
15: {
16: public int result;
17: public void methodPlus( int x, int y )
18: {
19: result = x + y;
20: }
21: }
22: class Class1
23: {
24: static void Main(string[] args)
25: {
26: Class2 instance1 = new Class2();
27: Class3 instance2 = new Class3();
28: Sample d1 = new Sample( instance1.methodMult );
29: Sample d2 = new Sample( instance2.methodPlus );
30: d1(2,3);
31: d2(4,5);
32: Console.WriteLine( instance1.result );
33: Console.WriteLine( instance2.result );
34: }
35: }
36: } |
|
異なるクラスのインスタンスに対するdelegateを使用したサンプル・プログラム5 |
Class2とClass3はまったく無関係なクラスであるが、同一の型のdelegateを作成することができる。 |
これを実行すると以下のようになる。
|
サンプル・プログラム5の実行結果 |
メソッドの戻り値と引数だけ合っていれば、同一の型のdelegateを作成することができ、それを呼び出すことができる。
|
このサンプル・ソースはここまで説明した知識だけで読みとれると思う。このように、delegateは自由度の高い機能なのである。
継承でも実現できるか?
異なるクラスのメソッドを1つのメソッド呼び出しで扱う、というのは何もdelegateだけが持つ機能ではない。クラスの継承や、interfaceの機能を使って実現することもできる。以下は継承を使って実現してみた例である。これをdelegateを使った場合と比較して考えてみよう。
1: using System;
2:
3: namespace ConsoleApplication25
4: {
5: abstract class ClassBase
6: {
7: public abstract int method( int x, int y );
8: }
9: class ClassMult : ClassBase
10: {
11: public override int method( int x, int y )
12: {
13: return x*y;
14: }
15: }
16: class ClassPlus : ClassBase
17: {
18: public override int method( int x, int y )
19: {
20: return x+y;
21: }
22: }
23:
24: class Class1
25: {
26: public static void calc( int x, int y, ClassBase instance )
27: {
28: int result = instance.method(x,y);
29: Console.WriteLine( result );
30: }
31: static void Main(string[] args)
32: {
33: ClassMult instance1 = new ClassMult();
34: ClassPlus instance2 = new ClassPlus();
35: calc( 2, 3, instance1 );
36: calc( 2, 3, instance2 );
37: }
38: }
39: } |
|
クラスの継承を用いてdelegateの機能を真似たサンプル・プログラム6 |
基底クラスでabstractなメソッドを定義し、それをオーバーライドしたメソッドに処理を記述する。 |
これを実行すると以下のようになる。
|
サンプル・プログラム6の実行結果 |
実行結果はサンプル・プログラム2とまったく同じである。
|
このサンプル・ソースは、28行目のメソッド呼び出しによって、掛け算をしたり、足し算をしたりする。機能面では、これまで説明したサンプル・ソースと似ているが、コーディングにはいくつもの違いが見られる。まず、継承を使う方法ではメソッド名を統一しておく必要がある。また、あらかじめ、基底クラス(ClassBase)でabstractなメソッド宣言をしておき、機能をオーバーライドする場合はoverrideキーワードを付けてメソッドを記述する必要がある。戻り値と引数が合っていれば使用できるdelegateと比較すれば、制約は大きいといえる。さらに、28行目を見て分かるとおり、具体的に呼び出すインスタンスとメソッドが直接記述されているのも同然であり、代表者としての役割を果たしているとはいい難い。
このようにdelegateは、delegateという1つの機能であって、継承やinterfaceとは異なる特徴を持っている。これらは、適切に使い分けられるべきものなのである。
Insider.NET 記事ランキング
本日
月間