デリゲートとラムダ式の書き換え =>演算子の利用

デリゲートの表現とラムダ式の表現と書き換えのコードを紹介します。

参考

デリゲートについて

デリゲートやFunc<T> Action<T> については下記の記事を参考にしてください。

ラムダ式について

ラムダ式については下記の記事を参考にしてください。

サンプルプログラム

UI

下図のUIを作成します。Buttonと複数行のTextBoxを配置します。

コード

下記のコードを記述します。Buttonのclickイベントを実装します。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace LambdaExpressionDelegate
{
  public partial class FormMain : Form
  {
    delegate int FuncDelegate(int a);
    
    public FormMain()
    {
      InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
      FuncDelegate function1 = new FuncDelegate(proc);
      FuncDelegate function2 = proc;

      Func<int, int> function3 = new Func<int, int>(proc);

      Func<int, int> function4 = delegate(int a) { 
        return a * a;
      };

      Func<int, int> function5 = (a) =>
      {
        return a * a;
      };

      textBox1.Text += "function1:" + Convert.ToString(function1(5)) + "\r\n";
      textBox1.Text += "function2:" + Convert.ToString(function2(5)) + "\r\n";
      textBox1.Text += "function3:" + Convert.ToString(function3(5)) + "\r\n";
      textBox1.Text += "function4:" + Convert.ToString(function4(5)) + "\r\n";
      textBox1.Text += "function5:" + Convert.ToString(function5(5)) + "\r\n";
      
    }

    private int proc(int a)
    {
      return a * a;
    }

  }
}

解説

クラシックなデリゲートの記述

下記のコードが従来のデリゲートのコード記述になります。デリゲートのコンストラクタの引数にメソッド名を渡します。
  FuncDelegate function1 = new FuncDelegate(proc);

デリゲートのタイプは別途定義されている下記のコードになります。
  delegate int FuncDelegate(int a);

参照されるメソッドは別途記述されている下記の"proc"を利用します。
private int proc(int a)
{
  return a * a;
}

クラシックなデリゲートの記述2

C# 2.0以降の場合は new 演算子を用いずに代入するだけで同様の処理が実現できます。
  FuncDelegate function2 = proc;

Func<T> Action<T>を利用したコード

C# 2.0で導入されたGenerics(ジェネリクス)を利用した「Func<T>」や「Action<T>」の利用により、その都度デリゲート型を定義する必要が無くなりました。

  Func<int, int> function3 = new Func<int, int>(proc);
がFunc<T>を利用したデリゲートのコード記述になります。デリゲートのコンストラクタの引数にメソッド名を渡す部分は従来と同じです。また、デリゲート型の宣言が不要になります。

参照されるメソッドは別途記述されている下記の"proc"を利用します。
private int proc(int a)
{
  return a * a;
}

匿名メソッドを利用したコード

デリゲートで呼び出される関数は、再利用される場合はメソッドして宣言したほうが良いですが、多くの場合再利用されるケースは少なく、そのデリゲートのみで利用されるものが多いです。呼び出し元が一つである場合は、メソッドとして記述せずに匿名メソッドで記述したほうが、コードの可読性が高くなります。
以下のコードはデリゲートで参照されるメソッドを匿名メソッドで記述したコードです。
  Func<int, int> function4 = delegate(int a) { 
    return a * a;
  };

デリゲートを匿名メソッドで記述する場合は以下の書式となります。
delegate (引数の型 引数名) {
  [メソッドの実装]
}
引数が複数の場合は以下となります。
delegate (引数の型1 引数名1, 引数の型2 引数名2, 引数の型3 引数名3, ...) {
  [メソッドの実装]
}

ラムダ式を用いた匿名メソッドのコード (式形式)

ラムダ式を用いると、さらにシンプルに記述できます。
  Func<int, int> function5 = (a) => a * a;
式形式のラムダ式で記述する場合は以下の書式となります。

引数が一つの場合

引数名 => (実装);

引数が複数の場合

(引数名1,引数名2,引数名3, ...) => (実装)

引数がない場合

() => (実装)

ラムダ式を用いた匿名メソッドのコード (ステートメント形式)

ラムダ式を用いると、さらにシンプルに記述できます。
  Func<int, int> function5 = (a) =>
  {
    return a * a;
  };
ステートメント形式のラムダで記述する場合は以下の書式となります。

引数が一つの場合

引数名 => {
   (実装)
 };

引数が複数の場合

(引数名1,引数名2,引数名3, ...) => {
   (実装)
 };
引数がない場合は以下の記述となります。

引数がない場合

() => {
   (実装)
 };

実行結果

プロジェクトを実行します。下図のウィンドウが表示されます。


[Button1]をクリックします。テキストボックスに下図の結果が表示されます。5つとも同じ動作のロジックのため、5行同じ内容の文字列が表示されます。


著者
iPentec Document 編集部
iPentec Document 編集部です。
快適な生活のための情報、価値のある体験やレビューを提供します。
掲載日: 2015-03-11
iPentec all rights reserverd.