C#/いまさらヒトに聞けないこといろいろ/デリゲート で出てきた例(ちょっと整理しますが) をつかって、汎用的なデリゲート、Action/Funcの使い方をメモっておきます

ちょっと整理

C#/いまさらヒトに聞けないこといろいろ/デリゲート のソースをもっとシンプルに整理してみます

namespace ConsoleApplication1
{
  delegate int Calculator(int x, int y);//delegateの宣言
  class Program
  {
    static void Main(string[] args)
    {
      calc(2, 3, methodPlus);
      calc(2, 3, methodMult);
    }

    public static void calc(int x, int y, Calculator instance)
    {
      int result = instance(x, y);
      Console.WriteLine(result);
    }

    public static int methodMult(int x, int y)
    {
      return x * y;
    }
    public static int methodPlus(int x, int y)
    {
      return x + y;
    }
  }
}

汎用的なデリゲートFunc

上では

  delegate int Calculator(int x, int y);

というデリゲートを宣言しましたが、引数がint,int,戻り値がint、っていう汎用的なデリゲート

 Func<int, int, int>

を使うことで、ソースは以下のように書き直すことができます

namespace ConsoleApplication1
{
    //delegate int Calculator(int x, int y);  //コメントアウトしちゃう
    class Program
    {
        static void Main(string[] args)
        {
            calc(2, 3, methodPlus);
            calc(2, 3, methodMult);
        }

        public static void calc(int x, int y, Func<int, int, int> instance)
        {
            int result = instance(x, y);
            Console.WriteLine(result);
        }

        public static int methodMult(int x, int y)
        {
            return x * y;
        }
        public static int methodPlus(int x, int y)
        {
            return x + y;
        }
    }
}

ソースからデリゲートの宣言を消すことが出来ました。こう書くと、いかにも関数を渡してるってかんじになりますねぇ。

いろいろな書き方

これら、全部おんなじ意味です

calc(2, 3, methodPlus);   // メソッドを渡す
calc(2, 3, new Func<int, int, int>(methodPlus));   // newして、渡す
calc(2, 3, new Func<int, int, int>(delegate(int x, int y) { return x + y; }));   // メソッドをその場で定義
calc(2, 3, new Func<int, int, int>((int x, int y) => { return x + y; }));   // ラムダ式
calc(2, 3, (int x, int y) => { return x + y; });   // ラムダ式で、デリゲート名を省略
calc(2, 3, (x, y) => { return x + y; });   // ラムダ式は型を省略できる
calc(2, 3, (int x, int y) => x + y);

戻り値のない汎用デリゲート Action

つぎにActionデリゲートですが、こちらは戻り値のないFuncってかんじです

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
  public class Program
  {
    static void Main(string[] args)
    {
      new Program().execute();
    }

    public void StringAction(string str)
    {
      Console.WriteLine("StringAction method start.");
      Console.WriteLine(str);
      Console.WriteLine("StringAction method end.");
    }

    public void execute()
    {
      // GenericsなdelegateをStringとして宣言
      Action<String> StringActionDele = new Action<String>(StringAction);
      //Action<String> StringActionDele = StringAction; // <-こういう書き方もしていい
      // delegate経由でメソッドを実行
      StringActionDele("StringActionDeleを直接呼び出しました");

      // メソッドの引数にdelegateインスタンスを渡すこともできる
      executeAction(StringActionDele);

      // Anonymousな感じで直接定義してもいい
      executeAction(
        new Action<String>(delegate(String str)
      {
        Console.WriteLine("Anonymous Delegate method start.");
        Console.WriteLine(str);
        Console.WriteLine("Anonymous Delegate method end.");
      })
      );

      // 最後はラムダ式。Actionなくなった。引数ひとつでvoidを戻すメソッドを
      // 渡すから、よろしくねって感じになる
      executeAction((str) =>
      {
        Console.WriteLine("Delegate method start.");
        Console.WriteLine(str);
        Console.WriteLine("Delegate method end.");
      });

      List<string> stringList = new List<string>();
      stringList.Add("こんにちは");
      stringList.Add("さようなら");
      stringList.ForEach(StringActionDele); // このメソッドで「処理」を渡してる
    }

    void executeAction(Action<String> actionDelegate)
    {
      actionDelegate("StringActionDeleをexecuteAction メソッドから呼び出しました");
    }
  }
}

関連リンク


この記事は

選択肢 投票
おもしろかった 0  
そうでもない 0  

現在のアクセス:3825


トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2012-07-24 (火) 01:22:39 (4287d)