ある条件にマッチしたものだけに特定の処理を行いたいという要件がありました。
条件自体は選択可能で実行時に決定されます。
最初は条件用のクラスを書いていたんですが、ふとデリゲートでもいいんじゃないかと思って、どこまでかけるか試して見ました。

まずは簡単に、匿名メソッドとマルチキャストデリゲートの説明を。

    // 単なるデリゲートの定義
    delegate bool Filter(Entity aEntity);

    // 匿名メソッドを使ってデリゲートを設定
    Filter tFilter = delegate(Entity aEntity) { return aEntity.Visible; }

    // マルチキャストデリゲート(同じデリゲートに追加。)
    tFilter += delegate(Entity aEntity) { return aEntity.Locked; }

    // デリゲートの実行
    bool tReturn = tFilter(aEntity);

例では、Visible == trueかつLocked == trueの場合、trueを返します。
このようにフィルターをある程度自由に組み替えつつ、複数組み合わせるケースには使えるかもしれません。

このデリゲートをプロパティとして持つクラスを定義してみましたが

public class FilterSet
{
    private Filter mFilter;
    public Filter Filter
    {
        get { return this.mFilter;}
    }
}

これはダメでした。FilterSet.Filter += …で書き込み権限がないと怒られます。

パブリックなメンバ変数として持った場合。

public class FilterSet
{
    public Filter Filter;
}

これはいけました。

なんとなくpublicはいやだなぁ。。。ということで、一工夫。

public class FilterSet
{
    private Filter mFilter;
    public event Filter
    {
        add { this.mFilter += value; }
        remove { this.mFilter -= value; }
    }

    public bool Accept(Entity aEntity)
    {
        return this.mFilter(aEntity);
    }
}
}

これもOK。微妙ですけど(笑

カテゴリー: 技術情報

5件のコメント

squld · 2007-05-29 09:38

コレはおもろい。

Javaだといちいちクラス作らなければ行けないところがdelegateで済むので、色々用途がありそう。
delegateテクニック集作ほしいな。

ステートメントをdelegate化
delegate化したいステートメントを選択して

  1. リファクタ.メソッド抽出
  2. 抽出したメソッドをdelegate化

で、簡単にテンプレートメソッド作れてイイ感じ。

delegateの速度
delegateはインタフェース呼び出し・関数呼び出しよりは遅いが、Method.Invokeよりはだいぶ速いっぽい。
https://www.microsoft.com/japan/msdn/msdnmag/issues/05/07/Reflection/default.aspx

koreyasu · 2007-05-29 12:59

ふと思ったんだけど、返り値がboolならAND取ってるってのは分かるんだけど…
返り値が単なるobjectの場合もあるわけだし、本当にAND取ってるのか分からない気がするOrz
後でちょっと調べる。

koreyasu · 2007-05-29 13:47

やはり問題があった。返り値は一番最後のDelegateのものが帰ってくる模様。

squld · 2007-05-29 21:56

delegateの引数にref指定のものを加えて、それを介して返値を返すようにすれば、一応ANDとかORとか制御できそう。

koreyasu · 2007-05-29 23:33

EventArgsとかそんな感じになってたっけ?
e.Cancel = trueとか各イベントリスナで指定されれると、イベントのキャンセルができるみたいなのがあった気がする。
まぁ、同じインスタンスが使われているのか、個別に作られてるかはわからんけど。

コメントを残す

メールアドレスが公開されることはありません。