委托方法与一般方法

时间:2012-05-22 17:26:47

标签: c# methods delegates

我想知道使用委托方法和使用常规方法[无代表]之间的区别。

例如:


使用代理:

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)

这两个有什么不同?

没有委托的方法更小更容易。但我发现编码员经常使用委托方法。

这背后的原因是什么?

4 个答案:

答案 0 :(得分:18)

想象一下您有一个搜索客户的功能的场景。最初你只想按名称搜索,所以你写了类似的东西:

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

他们看起来非常相似,不是吗?

现在,您的老板再次告诉您添加其他搜索功能,用户可能希望通过电话号码查找客户。它变得无聊,不是吗?

幸运的是,开发人员已经找到了一种方法,可以让其他开发人员更轻松地发明代理。使用它们可以创建一个更大的通用函数,帮助您避免一次又一次地重写相同的代码片段。

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中也得到了密集使用。只需google“委托c#”,你就会发现一个巨大的新世界! :)

答案 1 :(得分:3)

代表们是另一种情况。想象一下,你有一个班级应该回答另一个班级的事情,但你对第二个班级一无所知。在这种情况下,您可以在第一个中执行委托。

// 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 Aclass B一无所知,但它可以调用B的方法并获得结果。 Answer中的class B方法私有,而class A无法直接调用它。

MSDN

中了解详情

答案 2 :(得分:2)

代表的另一种用法:

如果没有委托,只有定义私有方法的类才能调用这些方法。通过在委托中包装方法,您可以将委托实例传递给其他类,并让它们使用适当的参数调用委托(作为回调),并最终在定义类中调用您的实际私有方法。


例如:

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会在This article处发言:

代表在以下情况下非常有用:

  • 正在调用一种方法。
  • 一个类可能希望有多个方法规范的实现。
  • 希望允许使用静态方法来实现规范。
  • 需要类似事件的设计模式(有关更多信息,请参阅“事件教程”)。
  • 调用者无需知道或获取定义该方法的对象。
  • 该实现的提供者希望将规范的实现“分发”给少数几个选择组件。
  • 需要简单的组合。

答案 3 :(得分: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"

在第一种情况下,它是在调用站点插入的委托的可选参数。