Delegate Methods vs General Methods

2020-02-04 20:21发布

问题:

I want to know the difference between using Delegate Methods and using General Methods[without Delegates].

For Example :


With Delegate :

delegate void DelMethod(string str);

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

Usage :

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

And Without Delegate :

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

Usage :

Method(string)

What are the differences of these two??

The method without delegate is smaller and easy. But I find coders using delegated Methods frequently.

What is the reason behind this??

回答1:

Delegates are for another situation. Imagine, that you have a class which should answer for something from another class, but you know nothing about the second class. In such situation you can do a Delegate in the first.

// 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 knows nothing about class B, but it can call B's methods and get it's results. The Answer method in class B is private and class A can't call it directly.

Read more in MSDN



回答2:

Imagine a scenario in which you have a function that searches a Customer. Initially you just want to search by name so you write something like:

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

Then your specifications change and you have to implement new ways of searching (let's say "search-by-address"). No problem, we refactor our old code to:

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;
}

They look very similar, don't they?

Now your boss tell again you to add another search functionality, the user may want to find customers by telephone number. It is getting boring, isn't it?

Fortunately developers have found a way to make other developers' life easier inventing delegates. Using them you could create one bigger, general function that helps you to avoid rewriting the same pieces of code again and again.

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

Now you do not have to create a specialized function each time you need a new way of searching customers, so you can write:

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

Delegates are also useful to manage events and are used intensively also in LINQ. Just google "delegates c#" and you will discover a huge new world! :)



回答3:

Another use of delegates:

Without the presence of delegates, only the class defining your private methods would be able to call those methods. With wrapping of methods inside a delegate, you could pass your delegate instance to other classes and let them invoke the delegate (as a callback) with the proper parameters and that would eventually call your actual private method within the defining class.


For Example :

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
        }

    }
}

In general MSDN has following to say at This article :

Delegates are useful when:

  • A single method is being called.
  • A class may want to have multiple implementations of the method specification.
  • It is desirable to allow using a static method to implement the specification.
  • An event-like design pattern is desired (for more information, see the Events Tutorial).
  • The caller has no need to know or obtain the object that the method is defined on.
  • The provider of the implementation wants to "hand out" the implementation of the specification to only a few select components.
  • Easy composition is desired.


回答4:

There is one particular scenario where the two calls will differ, ie when it comes to optional arguments. Consider these

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

DelMethod dm = Method;
dm();

//prints "hai"

But

Method();

//prints "bye"

In the first case, it is the optional argument of the delegate that is inserted at the call site.