ジェネリックなメソッドやデリゲートがもたらす新スタイル特集C#&VBジェネリック超入門(後編)(2/4 ページ)

» 2006年03月18日 00時00分 公開
[遠藤孝信,デジタルアドバンテージ]

ジェネリック・デリゲート

 ジェネリックの仕組みは、デリゲートの宣言にも適用できます。そのようなデリゲートは「ジェネリック・デリゲート」と呼ばれます(デリゲートって何だっけ? という人は、次項の【コラム】をまずご覧ください)。

 例えば、.NET Framework 2.0のクラス・ライブラリ(System名前空間)には、次のようなジェネリック・デリゲートの定義(宣言)が含まれています。

public delegate void Action<T>(T obj)

Public Delegate Sub Action(Of T)(obj As T)

ジェネリック・デリゲートであるAction<T>デリゲートの宣言

 これは「Action<T>デリゲート」(VBでは「Action(Of T)デリゲート」)と呼ばれます。このデリゲートは、パラメータを1つ取り、戻り値を持たないメソッドに対して汎用的に使用できるデリゲートです。

 例えば、次のようなメソッドがあるとしましょう。

void StringAction(string s) {
  Console.WriteLine(s);
}

Sub MyAction(ByVal s As String)
  Console.WriteLine(s)
End Sub

パラメータを1つ取り、戻り値を持たないメソッドの例

 このメソッドに対しては、次のように具体的な型(ここではstring型)を型パラメータに指定して、デリゲートのインスタンスを作成できます。

Action<string> myActionDelegate = new Action<string>(StringAction);

Dim myActionDelegate As Action(Of String) = AddressOf MyAction

ジェネリック・デリゲートのインスタンス作成

 ちなみに、VBでは次のようにも記述できます(デリゲートのコンストラクタを明示的に呼び出す書き方です)。

Dim myActionDelegate As New Action(Of String)(AddressOf MyAction)

VBでのジェネリック・デリゲートのインスタンス作成(別の記述方法)

 C#の場合にも、もっと省略した記述方法がありますが、それについては後述しています。

【コラム】 デリゲートの復習

 デリゲートとはメソッドを間接的に呼び出すためのものです。デリゲートの機能により「メソッドへのポインタ」を表すオブジェクトを作成することができます。デリゲートの宣言は、そのようなオブジェクトの「型」を定義しているといえます。

 いま、1つのstring型のパラメータを取り、戻り値としてstring型を返すようなメソッド「MyFunction」があるとしましょう。

 このとき、次のようにして「MyFuncDelegate」という名前のデリゲートを宣言できます。

delegate string MyFuncDelegate(string s);

Delegate Function MyFuncDelegate(ByVal s As String) As String

デリゲートの宣言

 次に、メソッド名をパラメータとして、デリゲートのインスタンス(=オブジェクト)を作成します。

MyFuncDelegate myfunc = new MyFuncDelegate(MyFunction);

Dim myfunc As MyFuncDelegate = AddressOf MyFunction

デリゲート・インスタンスの作成

 これで、MyFunctionメソッドを直接呼び出す代わりに、変数myfuncをメソッドのようにして呼び出すことができます。

string s = myfunc("Mike");

Dim s As String = myfunc("Mike")

デリゲート・インスタンスによるメソッドの呼び出し

 myfuncオブジェクトは、MyFunctionメソッドへのポインタといえます。このオブジェクトをほかのメソッドに渡して、別のところからメソッドを呼び出してもらう(コールバックしてもらう)といったことができるようになります。

 次のサンプル・プログラムは以上の内容をまとめたものです。

using System;

class DelegateSample
{
  // デリゲートの宣言
  delegate string MyFuncDelegate(string s);

  string MyFunction(string s) {
    return s + "サンこんにちは";
  }

  void CallDelegate(MyFuncDelegate f) {
    string s = f("Mary");
    Console.WriteLine(s);
  }

  void Sample() {
    // デリゲート・インスタンスの作成
    MyFuncDelegate myfunc = new MyFuncDelegate(MyFunction);

    // デリゲート経由でメソッドを呼び出す
    string s = myfunc("Mike");
    Console.WriteLine(s);
    // 出力:Mikeサンこんにちは

    // デリゲートを渡してメソッドを呼び出してもらう
    CallDelegate(myfunc);
    // 出力:Maryサンこんにちは
  }

  static void Main() {
    DelegateSample ds = new DelegateSample();
    ds.Sample();
  }
}

Imports System

Class DelegateSample

  ' デリゲートの宣言
  Delegate Function MyFuncDelegate(ByVal s As String) As String

  Function MyFunction(ByVal s As String) As String
    Return s + "サンこんにちは"
  End Function

  Sub CallDelegate(ByVal f As MyFuncDelegate)
    Dim s As String = f("Mary")
    Console.WriteLine(s)
  End Sub

  Sub Sample()
    ' デリゲート・インスタンスの作成
    Dim myfunc As MyFuncDelegate = AddressOf MyFunction

    ' デリゲート経由でメソッドを呼び出す
    Dim s As String = myfunc("Mike")
    Console.WriteLine(s)
    ' 出力:Mikeサンこんにちは

    ' デリゲートを渡してメソッドを呼び出してもらう
    CallDelegate(myfunc)
    ' 出力:Maryサンこんにちは
  End Sub

  Shared Sub Main()
    Dim ds As New DelegateSample()
    ds.Sample()
  End Sub
End Class

デリゲートを使用したサンプル・プログラム

   

Copyright© Digital Advantage Corp. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。