C#デリゲートの実際の使用[終了]


16

私は概念的にはC#デリゲートを理解していると思いますが、それらが役立つ実際の例を見つけるのに苦労しています。実際のアプリケーションでC#デリゲートがどのように使用されたのか、どのような問題により回避できるのかを詳しく説明してください。


2
.NETフレームワークのほぼすべてのクラスがいくつかのイベントのセットを公開するので、そこに行きます。これは、作業単位をカプセル化する方法にすぎません。たとえば、Cで一般的なバイナリツリー構造を実装しているとします。まあ、ツリーを順序付ける唯一の方法は、並べ替えの方法を知っている関数ポインターをパラメーターとして使用することです。
エドS.

回答:


16

GUIコードはデリゲートを使用して、ボタンのクリック、ウィンドウの移動などのイベントを処理します。デリゲートを使用すると、イベントが発生するたびに呼び出される関数を使用できます。例としては、データを保存する機能をインターフェースの「保存」ボタンにリンクすることが挙げられます。ボタンがクリックされると、データを保存する機能を実行するように設定されます。あなたのプログラム全体がユーザーが何かをするのを待っているかもしれず、あなたが彼らが最初に何をするかを知る方法がないので、それはGUIプログラミングで役に立ちます。デリゲートを使用すると、プログラムの機能をUIに接続して、ユーザーが希望する方法で操作できるようにすることができます。


2
++あなたは正しいですが、私はまだそれが嫌いです:-)なので、何年も前に代わりにこれを思いつきました
マイクダンラベイ

12

LINQのは、使用Func<T>してAction<T>、すべてのパラメータなどの場所にデリゲートを。

これらにより、ラムダ式をパラメーターとして使用し、パラメーターリストの一部として実行されるアクションを定義できます。


12

事実上、Observerパターンを使用するものはすべてデリゲートを実装するでしょう。

説明を読むと、おそらくそれらを使用するいくつかのシナリオを想像するでしょう。GUIイベント処理は一般的な例です。


+1、戦略パターンは実際にデリゲートが輝く場所です。つまり、何らかのメソッドが何らかの処理を行うクラスがありますが、何かを交換でき、直接的な依存関係がなく、エルゴデリゲートが必要です。イベントはデリゲートと同じニーズを満たしていることに注意してください。違いは、何らかの戻り値に反応する必要があるときにデリゲートを使用するのに対し、イベントを発生させるだけであるという点です。
-Homde

9

デリゲートは、非同期プログラミングで非常に便利です。

非同期的に処理を行うクラスとコールバックがあります。コールバック時にデリゲートメソッドを呼び出すことができます。クラスの実装は、デリゲートメソッドで説明されているロジックを実行します。


9

デリゲートは、中間パターンの穴の解決策として特に役立ちます。基本的に、多くの場合、固有の一連の命令を共通の一連の命令の中にラップする必要があります。一意のビットの前後の命令で状態を共有する必要がある場合は特に困難です。デリゲートを使用すると、デリゲートを関数に渡すことができます。関数は、beforeビットを実行し、デリゲートを実行してから、afterビットを実行します。


5

FortranやCのような非OOP言語の「昔」では、関数へのポインタである引数をサブルーチンで受け取ることができると非常に便利でした。たとえば、このqsort関数はユーザー提供の比較関数と連携します。常微分方程式を解くため、または関数を最適化するためのサブルーチンが多数あり、それらはすべて関数ポインターを引数として取ります。

ウィンドウシステムでは、すべての種類のコールバックが同じパターンに従います。

Lispでは、初期でも「関数型引数」またはFUNARGと呼ばれるものがありました。これは関数であるだけでなく、外部世界の一部を記憶して対話できるストレージコンテキストも含まれていました。

関数のアドレスを渡すとき、関数がメソッドであるオブジェクトのアドレスも渡す必要があることを除いて、これと同じニーズがOOP言語にも存在します。それはあなたが渡さなければならない二つのことです。したがって、デリゲートはそれだけであり、その古き良きパターンを引き続き使用できます。


3

以下は、DRYの原則に従う単純なコードを作成する際に、デリゲートがどれほど役立つかを示す簡単な例です。また、必要な場所にコードを非常に近づけることができます。

Action<Button, Action<Button>> prepareButton = 
    (btn, nxt) => { 
        btn.Height = 32;
        btn.Width= 64;
        nxt(btn);
    };

prepareButton(myBtn1, btn => btn.Text = "A");
prepareButton(myBtn2, btn => btn.Text = "B");
prepareButton(myBtn3, btn => btn.Text = "C");

デリゲートが提供する利点の実世界の例を次に示します。

protected override void PageInitialize()
{
    const string selectCodeFormat = "javascript:selectCode('{0}', '{1}');";
    const string onClick = "return toggleElement(this);";

    Func<HtmlGenericControl> getElement = null;
    Action<HtmlGenericControl> setElement = null, addChild = null;
    HtmlGenericControl level1Element = null, level2Element = null, level3Element = null, level4Element = null;
    string className = null, code = null, description = null;           

    using (var records = Core.Database.ExecuteRecords("code.SocCodeTree"))
    {
        while (records.Read())
        {
            code = records.GetString("Code");
            description = records.GetString("Description"); 

            if (records.GetString("Level4") != "")
            {
                className = "Level4";
                setElement = e => level4Element = e;
                getElement = () => level4Element;
                addChild = e => level3Element.Controls.Add(e);
            }
            else if (records.GetString("Level3") != "")
            {
                className = "Level3";
                setElement = e => level3Element = e;
                getElement = () => level3Element;
                addChild = e => level2Element.Controls.Add(e);
            }
            else if (records.GetString("Level2") != "")
            {
                className = "Level2";
                setElement = e => level2Element = e;
                getElement = () => level2Element;
                addChild = e => level1Element.Controls.Add(e);
            }
            else
            {
                className = "Level1";
                setElement = e => level1Element = e;
                getElement = () => level1Element;
                addChild = e => Root.Controls.Add(e);
            }

            var child = new HtmlGenericControl("li");
            child.Attributes["class"] = className;
            var span = new HtmlGenericControl("span") { 
                InnerText = code + " - " + description + " - " 
            };
            span.Attributes["onclick"] = onClick;
            child.Controls.Add(span);
            var a = new HtmlAnchor() { 
                InnerText = "Select", 
                HRef = string.Format(selectCodeFormat, code, description) 
            };
            child.Controls.Add(a);
            setElement(new HtmlGenericControl("ul"));
            child.Controls.Add(getElement());
            addChild(child);    
        }
    }
}

2

デリゲートとの最初の出会いは、Webサイトからファイルをダウンロードしてプログラムの更新(windowsフォームC#3.5)をチェックすることでしたが、プログラム全体をロックする更新チェックを回避するために、デリゲートとスレッドを使用して非同期に実行しました。


1

デリゲートを効果的に使用するStrategyパターンの興味深い実装を見てきました。(つまり、戦略はデリゲートです)

私が探していたのは、パスを見つけるためのアルゴリズムが、異なるアルゴリズムを使用できるように実行時に(再)割り当て可能なデリゲートであるパスファインディング用でした(BFS vs A *など)


1

従来のGoFパターンの多くはデリゲートで実装できます。たとえば、コマンドパターン、訪問者パターン、戦略パターン、ファクトリパターン、オブザーバーパターンは、多くの場合、単純なデリゲートで実装できます。時には、このクラスは、(コマンドが名前を必要とするかの戦略オブジェクトをシリアル化する必要などと)ほとんどの場合、使用して優れているAction<...>か、Func<...>はるかにエレガントな専用の一方式のインターフェースを作成するよりもです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.