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

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

■Action<T>デリゲートを使用するメソッド

 Action<T>デリゲートのようなジェネリック・デリゲートがクラス・ライブラリでわざわざ定義されているのは、当然ながらそのデリゲートを使用しているメソッドが存在するためです。

 List<T>ジェネリック・クラス(VBの場合にはList(Of T)ジェネリック・クラス、以下List<T>クラスと省略)のForEachメソッドは、Action<T>デリゲートを使用するメソッドの1つです。このメソッドのシグネチャは次のようになっています。

void ForEach(Action<T> action)

Sub ForEach(action As Action(Of T))

List<T>クラスのForEachメソッドのシグネチャ

 このメソッドは、コレクション(List<T>オブジェクト)内に格納されている要素の1つ1つに対して、パラメータで指定されたデリゲートを呼び出してくれるメソッドです。

 以下にList<T>クラスのForEachメソッドを使ったサンプル・プログラムを示します。

using System;
using System.Collections.Generic;

class GenericSample {

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

  void Sample() {

    List<string> stringList = new List<string>();
    stringList.Add("こんにちは");
    stringList.Add("さようなら");

    // デリゲート・インスタンスの作成
    Action<string> myActionDelegate = new Action<string>(MyAction);

    stringList.ForEach(myActionDelegate);
    // 出力:
    // こんにちは
    // さようなら
  }

  static void Main() {
    GenericSample gs = new GenericSample();
    gs.Sample();
  }
}

Imports System
Imports System.Collections.Generic

Class GenericSample

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

  Sub Sample()

    Dim stringList As New List(Of String)
    stringList.Add("こんにちは")
    stringList.Add("さようなら")

    ' デリゲート・インスタンスの作成
    Dim myActionDelegate As Action(Of String) = AddressOf MyAction

    stringList.ForEach(myActionDelegate)
    ' 出力:
    ' こんにちは
    ' さようなら
  End Sub

  Shared Sub Main()
    Dim gs As New GenericSample()
    gs.Sample()
  End Sub
End Class

List<T>クラスのForEachメソッドを使ったサンプル・プログラム

 stringListオブジェクトの各要素に対して、MyActionメソッドが呼び出され、その値が表示されるのが分かります。

 これまでコレクションの各要素を処理するには、順に要素を取り出し、それから処理するというのが一般的なスタイルでした。.NET Framework 2.0のクラス・ライブラリでは、デリゲートを活用することにより、各要素を処理するためのメソッド(の参照)をコレクションに渡しておき、各要素についてそのメソッドを呼び出させる、というスタイルが導入されたといえるでしょう。

■C# 2.0におけるデリゲート・インスタンス作成部分の簡略化

 ところで、デリゲートのインスタンスを作成するのには、上記のサンプル・プログラムにもあるように、VBでは「AddressOf演算子」でメソッド名を指定するだけなのに対して、C#では「new」が必要で記述が少し冗長になりがちでした。

 しかしC# 2.0では、以下のようにnew以降の部分をバッサリと省略して、いきなりメソッドを代入できるようになりました*

Action<string> myActionDelegate = new Action<string>(MyAction);
↓↓↓
Action<string> myActionDelegate = MyAction;

デリゲート・インスタンス作成部分の簡略化
C# 2.0ではデリゲート用の変数にメソッド名を代入するだけでよい。

* この機能はメソッド・グループ変換(method group conversions)と呼ばれます。


 デリゲート・インスタンス用の変数(上記のサンプル・プログラムでは「myActionDelegate」)も使うのをやめれば、上記のプログラムは次のようにだいぶすっきりします。

using System;
using System.Collections.Generic;

class GenericSample {

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

  void Sample() {

    List<string> stringList = new List<string>();
    stringList.Add("こんにちは");
    stringList.Add("さようなら");

    // デリゲートとしてメソッド名を直接指定
    stringList.ForEach(MyAction);
    // 出力:
    // こんにちは
    // さようなら
  }

  static void Main() {
    GenericSample gs = new GenericSample();
    gs.Sample();
  }
}

デリゲート・インスタンス作成部分を省略したC#のサンプル・プログラム

【コラム】 クラス・ライブラリのメソッドをデリゲートに使う

 C#にはforeach文、VBにはFor Each文があるため、通常はForEachメソッドをわざわざ使う必要性はそれほどないかもしれません。

 ただし少しトリッキーですが、上記のサンプル・プログラムに限れば、Console.WriteLineメソッドを呼び出しているMyActionメソッドに対してデリゲートを作成するのではなく、クラス・ライブラリのConsole.WriteLineメソッドに対して直接デリゲートを作成することでプログラムはすごくシンプルになります。

using System;
using System.Collections.Generic;

class GenericSample {

  void Sample() {
    List<string> stringList = new List<string>();
    stringList.Add("こんにちは");
    stringList.Add("さようなら");

    // Console.WriteLineをデリゲートとして指定
    stringList.ForEach(Console.WriteLine);
    // 出力:
    // こんにちは
    // さようなら
  }

  static void Main() {
    GenericSample gs = new GenericSample();
    gs.Sample();
  }
}

Imports System
Imports System.Collections.Generic

Class GenericSample

  Sub Sample()
    Dim stringList As New List(Of String)
    stringList.Add("こんにちは")
    stringList.Add("さようなら")

    ' Console.WriteLineをデリゲートとして指定
    stringList.ForEach(AddressOf Console.WriteLine)
    ' 出力:
    ' こんにちは
    ' さようなら
  End Sub

  Shared Sub Main()
    Dim gs As New GenericSample()
    gs.Sample()
  End Sub
End Class

Console.WriteLineメソッドを直接デリゲートとして使用するサンプル・プログラム

 ジェネリック・デリゲートをパラメータに取るメソッドを次にもう1つ見てみましょう。

Copyright© Digital Advantage Corp. All Rights Reserved.

RSSについて

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

メールマガジン登録

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