繁体   English   中英

Noobie代表基础知识C#

[英]Noobie Delegate Fundamentals C#

我不认为我理解委托方法的要点。 我见过的所有例子都是这样的:

class DelegateClass
{
    private List<string> ListString = new List<string>;
    delegate void DoSomethingToStringsDelegate(string s);

    public base()
    {
         ListString.Add("string"); ....
    }

    void ProcessStrings(DoSomethingToStringsDelegate dstsd)
    {
        foreach(string s in ListString)
            dstsd(s);
    }
}

class AClass
{
    ...
    void UseDelegateMethod(...)
    {
        DelegateClass ds = new DelegateClass();
        ds.ProcessStrings(new DoSomethingToStringsDelegate(PrintStrings);
    }
    void PrintStrings(string s)
    {
        System.out.Write(s);
    }
}

我不明白为什么只需要实现一个getListStrings()并自己遍历字符串,执行你需要做的事情,就像它是一个委托一样。

foreach( string s in ds.ggetListStrings() )
    System.out.Write(s);

私人成员的理由没有意义,因为我可以这样做:

global List<Strings> myListStrings = new List<Strings>();
ds.ProcessStrings(new DoSomethingToStringsDelegate(GetStrings);

void GetStrings(string s)
{
    myListStrings.Add(s);
}

...现在我有相同的列表,因为getListStrings()会做....

有人可以解释一下吗? 非常感谢!

delegate很有用,因为它实际上充当占用string ,用于将string作为参数并返回void任何方法。

如果您熟悉C,它类似于函数指针的工作方式。 在它的位置,您可以传递任何匹配签名和返回类型的方法。

例如,假设我想实现一个对一组对象进行排序的方法。 除了对象列表,我还可以传递一个委托,指示如何完成排序。 由于任何匹配委托的方法都可以传递,我可以在不同的方法之间动态切换,如果我想要减少或增加排序:

 delegate int comparisonDelegate(int p1, int p2);

 void SortArray(int[] array, comparisonDelegate cmp)
 {
      // determine order according to cmp
 }

 int CompareDecreasing(int p1, int p2)
 {
     if(p1 > p2) return -1;
     if(p1 < p2) return 1;
     return 0;
 }

 int CompareIncreasing(int p1, int p2)
 {
     if(p1 > p2) return 1;
     if(p1 < p2) return -1;
     return 0;
 }

现在我可以将SortArray称为:

 SortArray(array, new comparisonDelegate(compareDecreasing));
 SortArray(array, new comparisonDelegate(compareIncreasing));

我不明白为什么只需要实现一个getListStrings()并自己遍历字符串,执行你需要做的事情,就像它是一个委托一样。

这里的目标是创建一个可以对集合起作用的函数,但是可以进行任何操作。

通过示例更容易理解 - 要查看有用的方法和原因的一个很好的示例,请查看LINQ to Objects。

假设您要查看有多少字符串大于4个字符 - Enumerable.Count方法有一个带有委托的重载 - 可以使用的Func<T,bool>谓词。 这允许您指定任何操作并计算元素,即:

List<string> listOfStrings = GetListOfStrings();

int countOfStringsGreaterThanFourChars = listOfStrings.Count(s => s.Length > 4);

在这里,我们传递一个委托(通过lambda表达式创建),它给出了我们的标准。 通过使用带有委托的Count方法,它适用于任何标准,因此我们不必在每次需要不同条件时重新实现它。

假设我们想看看有多少字符串以“E”开头,我们可以使用:

int countOfStringsStartingWithE = listOfStrings.Count(s => s.StartsWith("E"));

同样,我们只需要编写与我们特定需求相关的代码,而不是复制遍历我们的集合并计算项目所需的所有样板代码......

在插图中使用委托可以更改方法的实现。

更好的例子是Comparer方法。 我不会进入IComparer接口,但足以说明,使用委托,您可以通过将委托传递给比较函数来修改排序方法的行为。

http://msdn.microsoft.com/en-us/library/system.collections.icomparer.aspx

首先,它允许您使用相同的方法签名注入不同的行为。 在一种情况下,您可能只想添加到列表中。 在另一种情况下,您可能希望添加到列表并写入日志文件,或者您可能想要在DoSomethingToStringsDelegate执行的任何其他操作。

从事件的角度来考虑它。 假设您有一个对项目列表进行一些处理的类,并且对于每个项目,消费您的类的人可能希望被通知项目已被处理(可能更新进度条,或更新系统的其他部分) , 随你)。 让我们把代表放在一边,让我们看看如何使用接口实现这一点:

public class MyClassThatDoesSomething
{
   private List<string> list = new List<string>();
   public void ProcessList()
   {
      foreach(var item in list)
      {
         ProcessItem(item);
         //how do we notify someone here??
      }
   }

   private void ProcessItem(string item){}
}

现在说有人正在消耗这个类:

var mc = new MyClassThatDoesSomething();
mc.ProcessList(); //how do I know when each one has been processed?

所以解决这个问题,让我们创建一个接口:

public interface IItemProcessed
{
   void ItemProcessed(string item);
}

我们现在可以重构我们原来的类:

public class MyClassThatDoesSomething
{
   private List<string> list = new List<string>();
   public void ProcessList()
   {
      foreach(var item in list)
      {
         ProcessItem(item);
         //how do we notify someone here??
         if(this.Listener != null)
         {
             this.Listener.ItemProcessed(item);
         }
      }
   }

   private void ProcessItem(string item){}

   public IItemProcessed Listener {get;set;}
}

而你班上的消费者现在可以这样做:

public class ProcessListener : IItemProcessed
{
   public void ItemProcessed(string item)
   {
      Console.WriteLine(item);
      //update progress bar, whatever
   }
}

var mc = new MyClassThatDoesSomething();
mc.Listener = new ProcessListener();
mc.ProcessList(); 

既然您已了解这一点,您可以将委托视为迷你接口,然后您可以将原始类更改为:

public class MyClassThatDoesSomething
{
   private List<string> list = new List<string>();
   public void ProcessList()
   {
      foreach(var item in list)
      {
         ProcessItem(item);
         //how do we notify someone here??
         if(this.Callback != null)
         {
             this.Callback(item);
         }
      }
   }

   private void ProcessItem(string item){}

   public Action<string> Callback {get;set;}
}

和消费者:

var mc = new MyClassThatDoesSomething();
mc.Listener = s =>
{
   Console.WriteLine(s);
   //update progress bar, whatever
}
mc.ProcessList(); 

总而言之,您可以将委托视为向外部人员提供一个简单的“钩子”到您的代码中的方式,以便让它们提供小块逻辑(想想Linq并过滤集合)或者像我已经演示过的回调/事件以上。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM