14

デリゲート メソッドの使用と一般的なメソッド [デリゲートなし] の使用の違いを知りたいです。

例えば ​​:


デリゲートの場合:

delegate void DelMethod(string str);

static void Method(string str)
{
    Debug.WriteLine(str);
}

使用法 :

DelMethod dm = new DelMethod(Method);
dm(string);

そしてデリゲートなし:

static void Method(string str)
{
    Debug.WriteLine(str);
}

使用法 :

Method(string)

この2つの違いは何ですか??

デリゲートを使用しない方法は、小さくて簡単です。しかし、委任されたメソッドを頻繁に使用しているコーダーを見つけます。

この背後にある理由は何ですか??

4

4 に答える 4

20

顧客を検索する関数があるシナリオを想像してみてください。最初は名前で検索したいので、次のように記述します。

public Customer Find(string name)
{
    foreach (var customer in database.Customers)
       if (customer.Name == name)
          return customer;
}

次に、仕様が変更され、新しい検索方法(「アドレスによる検索」など)を実装する必要があります。問題ありません。古いコードを次のようにリファクタリングします。

public Customer FindByName(string name)
{
    foreach (var customer in database.Customers)
       if (customer.Name == name)
          return customer;
}

public Customer FindByAddress(string address)
{
    foreach (var customer in database.Customers)
       if (customer.Address == address)
          return customer;
}

見た目はとても似ていますね。

これで、上司から別の検索機能を追加するように言われました。ユーザーは電話番号で顧客を検索したい場合があります。退屈になりつつありますね。

幸いなことに、開発者は、他の開発者の生活をより簡単に代理人を発明できるようにする方法を見つけました。それらを使用すると、同じコードを何度も書き直さないようにするための、より大きな一般的な関数を1つ作成できます。

public Customer Find(Predicate<Customer> p)
{
    foreach (var customer in database.Customers)
       if (p(customer))
          return customer;
}

これで、顧客を検索する新しい方法が必要になるたびに特殊な関数を作成する必要がなくなるため、次のように記述できます。

var byName = Find(a => a.Name == "lorem");
var byAddress = Find(a => a.Address == "ipsum");
var byTelephone = Find(a => a.Telephone == "dolor");

デリゲートはイベントの管理にも役立ち、LINQでも集中的に使用されます。「デリゲートc#」をグーグルで検索するだけで、巨大な新しい世界を発見できます。:)

于 2012-05-22T17:54:07.853 に答える
6

デリゲートは別の状況に対応しています。別のクラスから何かに応答する必要があるクラスがあるが、2 番目のクラスについて何も知らないと想像してください。このような状況では、最初にデリゲートを行うことができます。

// class where you know something
class A
{
   //delegate for answer
   public Func<bool> AskForSomething { get; set; }

   public void DoSomething()
   {
      //some code
      if(AskForSomething())
      {
          //do something
      }
      else
      {
          //do something else
      }
   }
}

class B
{
   public void Test()
   {
      A a = new A();
      a.AskForSomething = new Func<bool>(Answer);
      a.DoSomething();
   }

   private bool Answer()
   {
       return true;
   } 
}

Class Aは について何も知りませんがclass B、B のメソッドを呼び出して結果を取得できます。のAnswerメソッドclass Bプライベートでありclass A、直接呼び出すことはできません。

MSDNで詳細を読む

于 2012-05-22T17:34:10.473 に答える
4

2 つの呼び出しが異なる特定のシナリオが 1 つあります。つまり、オプションの引数に関してです。これらを考慮してください

delegate void DelMethod(string str = "hai");  
static void Method(string str = "bye")
{
    Debug.WriteLine(str);
}

DelMethod dm = Method;
dm();

//prints "hai"

しかし

Method();

//prints "bye"

最初のケースでは、呼び出しサイトに挿入されるデリゲートのオプションの引数です。

于 2013-12-22T03:56:39.063 に答える
3

デリゲートの別の使用法:

デリゲートが存在しない場合、プライベートメソッドを定義するクラスだけがそれらのメソッドを呼び出すことができます。デリゲート内でメソッドをラップすると、デリゲート インスタンスを他のクラスに渡し、適切なパラメーターを使用して (コールバックとして) デリゲートを呼び出すことができ、最終的に定義クラス内で実際のプライベート メソッドを呼び出すことができます。


例えば ​​:

namespace DelegatesSample
{
    public delegate void privateCallbackDelegate(string param1, int param2);
    public class A
    {
        private void DelegatedMehod(string param1, int param2)
        {
            //Code for some action
        }

        private void CallBusinessClass()
        {
            privateCallBackDelegate del = new privateCallBackDelegate(DelegateMethod);

            B b = new B();
            b.InvokeBusinessMethod(del);
        }
    }

    public class B
    {        
        public void InvokeBusinessMethod(privateCallbackDelegate d)
        {
            //Do Some calculations and when finished, call the callback delegate
            d("Done", result); //or d.Invoke or d.BeginInvoke
        }

    }
}

一般に、MSDN はこの記事で次のように述べています。

デリゲートは次の場合に役立ちます。

  • 1 つのメソッドが呼び出されています。
  • クラスには、メソッド仕様の複数の実装が必要な場合があります。
  • 仕様を実装するために静的メソッドを使用できるようにすることが望ましいです。
  • イベントのようなデザイン パターンが必要です (詳細については、イベントのチュートリアルを参照してください)。
  • 呼び出し元は、メソッドが定義されているオブジェクトを認識または取得する必要はありません。
  • 実装のプロバイダーは、仕様の実装を少数の選択されたコンポーネントのみに「配布」したいと考えています。
  • 簡単な構図が望まれます。
于 2012-05-22T17:57:35.017 に答える