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

【C#】C#でboost::bindを実装してみた(1)

boost::bindはなかなか便利で、
C#のデリゲートで実装してみました

デリゲート

C#では delegate という メソッドをカプセル化する機能がありました
実際自分から定義する必要なく、
Action と Func を使用することが多いです

Action と Func の簡単な例
// int を受け取るメソッドを定義する
public static void DelegateMethod(int i)
{
    // do do something
}
// Actionデリゲート保存
Action<int> handler = DelegateMethod;
// デリゲートを実行する
handler(10);

やりたいこと

オブジェクトに対して引数を部分的に束縛する
引用:bind(C++11) - cpprefjp - C++ Library Reference
イメージ
// 引数を束縛しActionデリゲートを作成する
Action action = Boost.Bind<int>(DelegateMethod,10);
// actionを実行:DelegateMethod(10)と同じ
action();

とりあえず、すべての引数を束縛する

public static class Boost
{
    public static Action Bind<P1>(Action<P1> action,P1 p1)
    {
      return delegate { return action(p1); };
    }
}

参考:
Boost.Bind を C# で作りたい(2) - melpon日記 - HaskellもC++もまともに扱えないへたれのページ

ラムダ式で書き直せます(C#3.0~)

public static Action Bind<P1>(Action<P1> action,P1 p1)
{
    return () => action(p1);
}
戻り値付きメソッド用バージョン
public static Func<TResult> Bind<P1,TResult>(Func<P1,TResult> func,P1 p1)
{
    return () => func(p1);
}

パラメータ2個までの実装

using System;
public static class Boost
{
    // T func(A1) -> T func()
    public static Func<TResult> Bind<P1,TResult>(Func<P1,TResult> func,P1 p1)
    { return () => func(p1); }
    public static Action Bind<P1>(Action<P1> action,P1 p1)
    { return () => action(p1); }

    // T func(A1,A2) -> T func()
    public static Func<TResult> Bind<P1,P2,TResult>(Func<P1,P2,TResult> func,P1 p1,P2 p2)
    { return () => func(p1,p2); }
    public static Action Bind<P1,P2>(Action<P1,P2> action,P1 p1,P2 p2)
    { return () => action(p1,p2); }
}