web-dev-qa-db-ja.com

デリゲートの利点は何ですか?

デリゲートを使用する利点と利点は何ですか?誰でも簡単な例を提供できますか?

24
Xaisoft

これらはコードの一部をカプセル化する優れた方法です。たとえば、ボタンにイベントハンドラーをアタッチすると、そのハンドラーはデリゲートになります。ボタンは、ボタンが何をするかを知る必要はなく、適切なタイミングで呼び出す方法を知っている必要があります。

別の例はLINQです-フィルタリング、投影などはすべて同じ種類のテンプレートコードを必要とします。変更点はすべて、フィルターやプロジェクションなどを表すロジックです。C#3のラムダ式(デリゲートまたは式ツリーに変換されます)を使用すると、非常に簡単になります。

var namesOfAdults = people.Where(person => person.Age >= 18)
                          .Select(person => person.Name);

(これはクエリ式として表すこともできますが、デリゲートから離れすぎないようにしてください。)

デリゲートのもう1つの考え方は、単一メソッドのインターフェース型です。たとえば、EventHandlerデリゲート型は次のようになります。

public interface IEventHandler
{
    void Invoke(object sender, EventArgs e)
}

ただし、フレームワークでのデリゲートサポートにより、デリゲートを一緒にチェーンしたり、非同期的に呼び出したり、イベントハンドラーとして使用したりできます。

デリゲートとイベントの詳細については、 トピックに関する私の記事 を参照してください。その焦点はイベントですが、デリゲートもカバーします。

44
Jon Skeet

これはかなり漠然としたトピックですが、考慮すべき点がいくつかあります-

デリゲートは基本的に、よりクリーンで簡単な関数ポインターです。 C++で関数ポインターが使用された場所ならどこでも、デリゲートと考えることができます。

デザインでそれらを使用する利点:

  • コードを簡単に再利用できる
  • 設計に大きな柔軟性を提供できます
  • 他の機能にフックする簡単な方法を提供するため、簡単に拡張可能なライブラリとクラスを開発できます(たとえば、LINQのwhere句はデリゲート[Func<T,bool>]を使用してフィルタリングできます。 Whereメソッドのコード

潜在的な欠点:

  • それらは~can~、特に単純に使用された場合、より読みにくいコードにつながります
  • 制御不能なサードパーティのコードが呼び出されるため、コンポーネントに予期しない動作が発生する可能性があります(たとえば、誰かがデリゲートをイベントの1つにアタッチして無限ループを引き起こすと、クラスが不適切に見える可能性があります。それはあなたとは関係ありませんが)
12
Reed Copsey

デリゲートには、3つの目的があります。

  1. Observerパターンの単純化された実装
  2. コールバックの簡略化された実装
  3. コードの匿名の(再利用できない)ブロック

観察者

public class Something
{
    public event EventHandler SomethingHappened;
}

public class SomethingConsumer
{
    private mySomething = new Something();

    public void WireUpEvents()
    {
        mySomething.SomethingHappened += whenSomethingHappened;
    }

    private void whenSoemthingHappened(object sender, EventArgs e)
    {
        // do something
    }
}

CallBack

public void DoSomethingAsynchronously(EventHandler callBack)
{
    // long running logic.
    callBack(this, EventArgs.Empty);
}

匿名の再利用できないコード

public void DoSomethingReusably(Action nonReusableCode)
{
    // reusable code
    nonReusableCode();
    // more reusable code
}

public void DoALotOfSomething()
{
    DoSomethingReusably(() => { /* non-reusable code here */ });
    DoSomethingReusably(() => { /* non-reusable code here */ });
    DoSomethingReusably(() => { /* non-reusable code here */ });
}

すべての場合において、それはただの簡潔さを提供することの問題です。

6
Michael Meadows

C#のデリゲートはeqvです。 Cの関数ポインタへのリンクですが、作成元のクラスインスタンスへの参照も含まれています。

Windowsフォームのすべてのイベントハンドラーはデリゲートです。

2
Joshua

何と比較した場合の利点?デリゲートは便利なものになる可能性があり、適度に複雑な多数のC#コードの中で確かにその位置を占めます。 (クラスでイベントを使用する場合は常に、マルチキャストデリゲートを暗黙的に使用しています)。構文と使用法の紹介が必要な場合は、以下の記事をお勧めします。

2
Noldorin

免責事項:デリゲートの使用方法が意図された方法であるとは言いませんが、それは一例です。

私はこれを1度だけ使用しましたが、基本的に私たちのアプリでは、ユーザーがステップの[完了]ボタンをクリックすると、ルーティングページに移動して次に送信する場所を決定します。したがって、技術的には、「完了」をクリックしたステップは、ルーティングするまで実際には完了しません。しかし、私は別のページにいるので、彼らがいた場所に簡単にアクセスできませんでした。

だから私がしたことは、「完了」をクリックしたときに特別な処理(この場合はメール)を必要とするいくつかのステップのデリゲートを作成し、次のページでルーティングしたときにデリゲートの存在を確認し、私の「保存された」イベントを発生させるためにそれを呼び出しました。

クリエイティブ:多分、間違っている:多分、機能している:間違いなく。

私が言ったように、それがどのように使用されることが意図されていたのではないかもしれませんが、コーディングは科学と同じくらいアートですよね?

2
Jeff Keslinke

初期のJavaデリゲートやコマンドルーティングの概念がなかったGUIフレームワークを覚えています。何かを実行するボタンを作成するには、サブクラスボタンをオーバーライドする必要がありましたクリックメソッドを使用すると、アプリケーションコードのほんの少しだけのUI要素サブクラスがたくさん作成されます。

そのクリックを処理するコードはどこかに行く必要があり、OO JavaまたはC#のような言語では、クラスに行く必要がありますが、デリゲートはそれを許可しますこれは、多くのコードがフォームクラスでさまざまなことを実行しすぎることにつながりますが、それは別の問題です。

1
Anthony