読者です 読者をやめる 読者になる 読者になる

CubicLouve

Spring_MTの技術ブログです。https://github.com/SpringMT (http://spring-mt.tumblr.com/ からの移転)

delegateを触ってみる

C#

あんまり今まで縁がなかったdelegateを触ってみる。

参照 : http://ufcpp.net/study/csharp/sp_delegate.html

C#では、delegateはメソッドを代入するための変数の型、メソッドを参照するための型。

  • サンプル(これはクラスメソッドの例)
using System;

// int型の引数一つをとって何も値を返さないdelegate型
delegate void TestDelegateMethod(int a);

class DelegateTest
{
  static void Main()
  {
    TestDelegateMethod a = A;
    a(256);
  }
  static void A(int n)
  {
    Console.Write("A{0}がよばれました\n", n);
  }
}

インスタンスメソッドでもクラスメソッドでも代入可能

using System;

// 引数を取らず、何も返さない
delegate void ShowMessage();

class Person
{
  string name;
  public Person(string name) { this.name = name; }
  public void ShowName() { Console.Write("名前 {0}\n", this.name); }
}

class TestDelegate
{
  static void Main()
  {
    Person p = new Person("テスト");
    ShowMessage show = p.ShowName;
    show();
  }
}

複数メソッドを代入可能(マルチキャストデリゲート)

+= 演算子で複数のメソッドを代入可能です。

using System;

delegate void ShowMessage();

class DelegateTest
{
  static void Main()
  {
    ShowMessage a = A;
    a += B;
    a += C;
    a();
  }

  static void A() { Console.Write("Aだよ\n"); }
  static void B() { Console.Write("Bだよ\n"); }
  static void C() { Console.Write("Cだよ\n"); }
}

非同期呼び出し

デリゲート型を定義すると、BeginInvoke と EndInvoke というメソッドを生やす。

BeginInvokeは、System.AsyncCallback デリゲート型の引数および object 型の引数をとり、System.IAsyncResult インターフェース型の値を返す。 EndInvoke はデリゲート型の定義時に ref または out キーワードを付けた引数および System.IAsyncResult インターフェース型の引数を持ち、デリゲートの戻り値と同じ型の戻り値を返す。

using System;
using System.Threading;

namespace A
{
  public delegate void ShowMessage(int n);

  public class DelegateTest
  {
    static void Main()
    {
      const int N = 6;
      ShowMessage asyncCall = AsyncMethod;

      // asysCall を非同期を呼び出し
      // BeginInvokeで                                                                                                            
      IAsyncResult ar = asyncCall.BeginInvoke(N, null, null);

      for (int i=0; i<N; ++i)
      {
        Thread.Sleep(600);
        Console.Write("Main {0}\n", i);
      }

      // asyncCall の処理が終わるの待つ
      asyncCall.EndInvoke(ar);
      Console.Write("処理完了");
    }

    static void AsyncMethod(int n)
    {
      for(int i=0; i<n; ++i)
      {
        Thread.Sleep(1000);
        Console.Write("AsyncMethod {0}\n", i);
      }
    }

  }
}