デリゲートとは何ですか?[閉まっている]


152

デリゲートの実際の役割は何ですか?

私はインタビューで何度もこの質問をされてきましたが、インタビュアーが私の答えに満足したとは思いません。

誰かが私に最良の定義を一文で実用的な例を挙げて教えてもらえますか?


21
好奇心から、あなたはそれをどのように修正できるかを説明できるように、あなたは何を答えましたか?
Anthony Forloney、2010年

6
この質問は締め切られましたが、126の賛成票と65人がお気に入りとしてマークしたのは興味深いことです。広すぎるとしても、非常に良い質問だと思います。
リッチ

回答:


171

デリゲートは「関数へのポインタ」と考えるのが好きです。これはC日までさかのぼりますが、アイデアはまだ保持されます。

アイデアは、コードの一部を呼び出すことができる必要があるということですが、これから呼び出すコードの一部は、実行時までわかりません。したがって、その目的で「デリゲート」を使用します。デリゲートは、たとえば、イベントハンドラーなどのさまざまなイベントに基づいてさまざまなことを行う場合に便利です。

ここにあなたが見ることができるC#のリファレンスがあります:

たとえば、C#では、実行したい計算があり、実行時までわからない別の計算方法を使用したいとします。したがって、次のような計算方法がいくつかあるかもしれません。

public static double CalcTotalMethod1(double amt)
{
    return amt * .014;
}

public static double CalcTotalMethod2(double amt)
{
    return amt * .056 + 42.43;
}

次のようにデリゲートシグネチャを宣言できます。

public delegate double calcTotalDelegate(double amt);

次に、デリゲートをパラメータとして受け取るメソッドを次のように宣言できます。

public static double CalcMyTotal(double amt, calcTotalDelegate calcTotal)
{
    return calcTotal(amt);
}

そしてCalcMyTotal、使用したいデリゲートメソッドを渡すメソッドを呼び出すことができます。

double tot1 = CalcMyTotal(100.34, CalcTotalMethod1);
double tot2 = CalcMyTotal(100.34, CalcTotalMethod2);
Console.WriteLine(tot1);
Console.WriteLine(tot2);

19
C.でシンプルだが効果的な関数ポインタにうなずきための1
エイデンベル

3
あなたの回答に関連する1つの質問。通常の方法で関数を呼び出すのとどう違うのですか?それだけで実行時に知られていないのですか?
2010年

1
@NAVEED-私の最新の編集を参照し、例を含めました。実際のメソッド呼び出しに関しては、上記の例の通常のメソッド呼び出しとは何の違いもありません(calcTotal(amt)がデリゲートを呼び出しています)が、デリゲートの力はそれらをパラメーターとして使用できることです。メソッドにさまざまな動作を持たせたい場合など。他にも使用できるものがたくさんありますが、これは単なる例です。お役に立てば幸いです。
dcp 2010年

これは、実行時に知られ、そして結合された機能ではなく、自由な機能ではありませんだ-非静的メソッドを割り当てるFooデリゲートにして呼び出すthis.Foo()関数ポインタを行うようにではなく、静的な関数を(Cで、あなたは多くの場合、余分な持っているvoid*にパラメータをthis関数ポインタに渡す)
ピートカーカム2010年

1
C / C ++の関数ポインターとの類似性を確立する迅速で効果的な例の場合は+1。とても有難い!
G21 2013

19

デリゲートは単に関数ポインタです。
デリゲートを実行するメソッドを割り当てるだけです。その後、コードでInvokeを介してそのメソッドを呼び出すことができます。

デモするコード(これはメモリから書き込んだため、構文がオフになっている可能性があります)

delegate void delMyDelegate(object o);

private void MethodToExecute1(object o)
{
    // do something with object
}

private void MethodToExecute2(object o)
{
    // do something else with object
}

private void DoSomethingToList(delMyDelegate methodToRun)
{
    foreach(object o in myList)
        methodToRun.Invoke(o);
}

public void ApplyMethodsToList()
{
    DoSomethingToList(MethodToExecute1);
    DoSomethingToList(MethodToExecute2);
}

16

ここから撮影

Qデリゲートとは何ですか?
Aオブジェクトがリクエストを受信すると、オブジェクトはリクエスト自体を処理するか、リクエストを2番目のオブジェクトに渡して作業を実行できます。オブジェクトが要求を渡すことを決定した場合、そのオブジェクトは、要求を処理する責任を2番目のオブジェクトに転送したと言います。

または、簡単な疑似例として、何かがobject1にリクエストを送信します。次に、object1はリクエストと自身をobject2-デリゲートに転送します。object2はリクエストを処理し、いくつかの作業を行います。(注:上記のリンクは良い例です)


上記のリンクの例では、委任が正しく記述されていません。
Hardik9850 2017年


4

デリゲートは、メソッドを参照できるオブジェクトです。したがって、デリゲートを作成すると、メソッドへの参照を保持できるオブジェクトが作成されます。さらに、この参照を通じてメソッドを呼び出すことができます。したがって、デリゲートは、参照先のメソッドを呼び出すことができます。デリゲートの主な利点は、メソッドへの呼び出しを指定できることですが、実際に呼び出されるメソッドは、コンパイル時ではなく実行時に決定されます。

単純なデリゲート

Declaration of delegate:
delegate-modifier delegate return-type delegate-name(parameters)
Implementation of delegate:
Delegate-name delegate-object=new Delegate-name(method of class)

http://knowpacific.wordpress.com/2012/01/26/delegate/


2

ここでは、デリゲート、マルチキャストデリゲート、およびそれらの使用法について説明します。デリゲートは、オブジェクト内のメソッド参照を保持するタイプです。タイプセーフ関数ポインタとも呼ばれます。デリゲートは、メソッドシグネチャを定義する型と言えます。

デリゲートをインスタンス化するとき、そのインスタンスを互換性のあるシグネチャを持つ任意のメソッドに関連付けることができます。デリゲートインスタンスを介してメソッドを呼び出す(または呼び出す)ことができます。デリゲートは、メソッドを引数として他のメソッドに渡すために使用されます。イベントハンドラーは、デリゲートを通じて呼び出されるメソッドにすぎません。デリゲートを使用する利点は、呼び出し元からのメソッドの呼び出しをカプセル化することです。デリゲートを効果的に使用すると、アプリケーションのパフォーマンスが向上します。デリゲートにはいくつかのプロパティがあります

Delegates are like C++ function pointers but are type safe.
Delegates allow methods to be passed as parameters.
Delegates can be used to define callback methods.
Delegates can be chained together; for example, multiple methods can be called on a single event.
Methods do not have to match the delegate signature exactly.

public delegate type_of_delegate delegate_name()//宣言

You can use delegates without parameters or with parameter list
If you are referring to the method with some data type then the delegate which you are declaring should be in the same format. This is why it is referred to as type safe function pointer. Here I am giving an example with String.

次の例は、デリゲート操作を示しています。

    namespace MyDelegate
    {
        class Program
        {
            private delegate void Show(string s);


            // Create a method for a delegate.
            public static void MyDelegateMethod(string me

ssage)
        {
            System.Console.WriteLine(message);
        }

        static void Main(string[] args)
        {
            Show p = MyDelegateMethod;
            p("My Delegate");
            p.Invoke("My Delegate");
            System.Console.ReadLine();
        }
    }
}

マルチキャストデリゲートとは何ですか?

複数のメソッドの参照を保持するデリゲートです。マルチキャストデリゲートには、voidを返すメソッドのみを含める必要があります。それ以外の場合は、実行時例外があります。

 delegate void MyMulticastDelegate(int i, string s);
 Class Class2
 {
  static void MyFirstDelegateMethod(int i, string s)
  {
    Console.WriteLine("My First Method");
  }

  static void MySecondDelegateMethod(int i, string s)
  {
    Console.WriteLine("My Second Method");
  }

  static void Main(string[] args)
  {
    MyMulticastDelegate Method= new MyMulticastDelegate(MyFirstDelegateMethod);
    Method+= new MyMulticastDelegate (MySecondDelegateMethod);
    Method(1,"Hi");             // Calling 2 Methodscalled
    Method-= new MyMulticastDelegate (MyFirstDelegateMethod);
    Method(2,"Hi");             //Only 2nd Method calling
  }
}

ここでは、デリゲートは+ =演算子を使用して追加され、-=演算子を使用して削除されます。

デリゲート型は、.NET FrameworkのDelegateクラスから派生します。デリゲートタイプはシールされています。派生させることはできません。インスタンス化されたデリゲートはオブジェクトであるため、パラメーターとして渡すか、プロパティに割り当てることができます。これにより、メソッドはデリゲートをパラメーターとして受け入れ、後でデリゲートを呼び出すことができます。これは非同期コールバックと呼ばれます。


1

Delegateパターンの優れた説明と実用的な実装は、Googleコレクション転送クラス(および、Decoratorパターン)にあります。


1

イベント通信では、送信者はどのオブジェクトがイベントを処理するかを認識していません。デリゲートはメソッドの参照を保持する型です。デリゲートにはシグネチャがあり、そのシグネチャに一致するメソッドへの参照を保持しているため、デリゲートはタイプセーフな関数ポインターのようなものです。

button1.Click + = new System.EventHandler(button1_Click)System.EventHandlerは、ここではデリゲートとして宣言されています。

デリゲートは、実行時に呼び出すコードがわからない場合に使用されるので、そのときにデリゲートを使用してイベントを処理します。

http://msdn.microsoft.com/en-us/library/ms173171(v=vs.80).aspx


1

デリゲートオブジェクトは、 何かが、そのオブジェクトに発生したときに別のオブジェクトを調べているオブジェクトです。たとえば、何かがあなたの車に起こった場合、あなたの修理人はあなたの代理人です。あなたはあなたの修理人のところへ行き、あなたに車を修理するように彼に頼みます(一部の人は自分で車を修理することを好むが、その場合、彼らは彼らの車のための彼ら自身の代理人です)。


1

デリゲートは、関数へのポインタを表すオブジェクトです。ただし、次の点で通常の関数ポインタではありません。

1)オブジェクト指向ですか

2)タイプセーフである、つまり、メソッドを指すことができるだけであり、メソッドが指す生のメモリアドレスを読み取ることができない

3)強く型付けされている。シグネチャに一致するメソッドのみを指すことができます。

4)同時に複数のメソッドを指すことができます。


1

デリゲートは主にイベントで使用されます。

必要性は:

プログラムを実行するときにコードを実行したくない。プログラムを実行した後、イベントが発生するたびにそのコードを実行します。

例:

  1. コンソールアプリケーション -コードは、プログラムの実行時にのみ実行できます。(Mainメソッド内に記述)
  2. Windowsアプリケーション(ユーザーインターフェイスプログラミング)-プログラムの実行後にボタンをクリックすると、コードを実行できます。

これは彼らが言うことです、あなたはコンパイル時にどのメソッドが呼び出されるかわかりません。あなたはそれがボタンをクリックしたときである実行時にのみそれを知っています。

デリゲートがないと、ユーザーインターフェイスプログラミングはできません。ボタンをクリックしたり、テキストボックスに入力したり、ドロップダウンリストのアイテムを選択したりするなどのイベントをユーザーが行うたびにコードを実行しているためです。


0

デリゲートは、タスクが委任される対象です。委任の主な目的は、コードを分離し、柔軟性と再利用性を高めることです。

プログラミング、特にオブジェクト指向プログラミングでは、これは、メソッドが何らかの処理を行うために呼び出されると、参照先の別のオブジェクトのメソッドにその処理を渡すことを意味します。オブジェクトが事前定義されたメソッドのセットに準拠している限り、参照は任意のオブジェクトを指すことができます。これを「インターフェイスへのプログラミング」と呼びます(具体的なクラス実装へのプログラミングではありません)。インターフェイスは基本的に汎用テンプレートであり、実装はありません。それは単にレシピ、メソッドのセット、前提条件と事後条件(ルール)を意味します。

簡単な例:

SomeInterface
{
   public void doSomething();
}


SomeImplementation implements SomeInterface
{
   public void doSomething()
   {
      System.err.println("Was it good for you?");
   }

}


SomeCaller
{
   public void doIt(SomeInterface someInterface)
   {
      someInterface.doSomething();
   }
}

これで、SomeCallerのコードを変更せずに、いつでも好きな実装を使用できることがわかりdoIt()ます。これは、渡される型が具体的ではなく、インターフェースであるため抽象的だからです。Javaの世界では、これは多くの場合、サービス(特定のインターフェースを介してそれ自体をサービスとしてアドバタイズするオブジェクト)を呼び出し、次にサービスがデリゲートに呼び出しを行うサービスパラダイムで表されます。サービスのメソッドは、粒度の粗いタスク(makePayment()、createNewUser()など)として名前が付けられていますが、デリゲートの型が具体的な実装ではなくインターフェイスであるデリゲートの種類によって、デリケートな機能が内部的に機能する場合、内部的には多くのことが行われます。

SomeService
{
    SomeInterface someImplementation = ... // assign here
    SomeOtherInterface someOtherImplementation = ... // okay, let's add a second

    public void doSomeWork()
    {
         someImplementation.doSomething();
         someOtherImplementation.doSomethingElse();
    }
}

(注:実装がどのように割り当てられるかは、このスレッドの範囲を超えています。制御の逆参照と依存性注入。)


-2

デリゲートは実際には「関数ポインタ」ではありませんが、PHPのような動的言語のように見える場合があります。



$func = 'foo';
$func();

function foo() {
    print 'foo';
}

またはJavaScriptであなたは次のようなことをすることができます:


var func = function(){ alert('foo!'); }
func();


2
これは委任の例ではありません。あなたの例では、基本的に変数が参照する文字列と同じ名前の関数を探す変数関数と呼ばれるものを使用しています。変数関数を参照してください:php.net/manual/en/functions.variable-functions.php
Aquarelle
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.