简体   繁体   English

Noobie代表基础知识C#

[英]Noobie Delegate Fundamentals C#

I dont think I understand the point of a delegate method. 我不认为我理解委托方法的要点。 All the examples I have seen do something like this: 我见过的所有例子都是这样的:

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

I dont understand why this is needed when you could simply just implement a getListStrings() and iterate through the strings yourself, doing what you needed to do, as if it was a delegate. 我不明白为什么只需要实现一个getListStrings()并自己遍历字符串,执行你需要做的事情,就像它是一个委托一样。

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

Private members reason doesnt make sense because I could just do: 私人成员的理由没有意义,因为我可以这样做:

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

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

...and now I have the same list, as a getListStrings() would do .... ...现在我有相同的列表,因为getListStrings()会做....

Can someone please explain? 有人可以解释一下吗? Thanks so much! 非常感谢!

The delegate is useful because it actually acts as a placeholder for any method that takes a string as parameter and returns void . delegate很有用,因为它实际上充当占用string ,用于将string作为参数并返回void任何方法。

If you are familiar with C, it is similar to how a function pointer works. 如果您熟悉C,它类似于函数指针的工作方式。 In its place you can pass any method that matches the signature and return type. 在它的位置,您可以传递任何匹配签名和返回类型的方法。

For example let's say I want to implement a method that sorts a group of objects. 例如,假设我想实现一个对一组对象进行排序的方法。 In addition to the object list I can also pass a delegate that indicates how the sort is to be done. 除了对象列表,我还可以传递一个委托,指示如何完成排序。 Since any method matching the delegate can be passed, I can then dynamically switch between different methods if I want for example decreasing or increasing sort: 由于任何匹配委托的方法都可以传递,我可以在不同的方法之间动态切换,如果我想要减少或增加排序:

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

Now I can call SortArray as: 现在我可以将SortArray称为:

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

I dont understand why this is needed when you could simply just implement a getListStrings() and iterate through the strings yourself, doing what you needed to do, as if it was a delegate. 我不明白为什么只需要实现一个getListStrings()并自己遍历字符串,执行你需要做的事情,就像它是一个委托一样。

The goal here is to make a function that will work on the collection, but do any operation. 这里的目标是创建一个可以对集合起作用的函数,但是可以进行任何操作。

This is easier to grasp by example - to see a great example of how and why this is useful, look at LINQ to Objects. 通过示例更容易理解 - 要查看有用的方法和原因的一个很好的示例,请查看LINQ to Objects。

Suppose you want to see how many of your strings are greater than 4 characters - the Enumerable.Count method has an overload that takes a delegate - a Func<T,bool> predicate that can be used. 假设您要查看有多少字符串大于4个字符 - Enumerable.Count方法有一个带有委托的重载 - 可以使用的Func<T,bool>谓词。 This lets you specify any operation and count the elements, ie: 这允许您指定任何操作并计算元素,即:

List<string> listOfStrings = GetListOfStrings();

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

Here, we're passing a delegate (created via a lambda expression) that gives us our criteria. 在这里,我们传递一个委托(通过lambda表达式创建),它给出了我们的标准。 By having a Count method that takes a delegate, it works for any criteria, so we don't have to reimplement this every time we want a different condition. 通过使用带有委托的Count方法,它适用于任何标准,因此我们不必在每次需要不同条件时重新实现它。

Say we want to see how many strings start with "E", we could just use: 假设我们想看看有多少字符串以“E”开头,我们可以使用:

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

Again, we only have to write the code that's relevant to our specific need , not duplicate all of the boilerplate code that would be required to loop through our collection and count the items... 同样,我们只需要编写与我们特定需求相关的代码,而不是复制遍历我们的集合并计算项目所需的所有样板代码......

Using a delegate in your illustration allows you to change out the implementation of the method. 在插图中使用委托可以更改方法的实现。

A better example is that of a Comparer method. 更好的例子是Comparer方法。 I won't get into the IComparer interface, but suffice it to say that, using a delegate, you would be able to modify a sort method's behavior by passing it a delegate to a comparison function. 我不会进入IComparer接口,但足以说明,使用委托,您可以通过将委托传递给比较函数来修改排序方法的行为。

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

For one, it allows you to inject different behaviors with the same method signature. 首先,它允许您使用相同的方法签名注入不同的行为。 In one case you might want to simply add to your list. 在一种情况下,您可能只想添加到列表中。 In another case you might want to add to the list and write to a log file, or whatever else you might want to do in a DoSomethingToStringsDelegate . 在另一种情况下,您可能希望添加到列表并写入日志文件,或者您可能想要在DoSomethingToStringsDelegate执行的任何其他操作。

Think of it in terms of events. 从事件的角度来考虑它。 Say you have a class that does some processing on a list of items, and for each item, someone consuming your class may want to be notified that an item has been processed (maybe update a progress bar, or update some other part of the system, whatever). 假设您有一个对项目列表进行一些处理的类,并且对于每个项目,消费您的类的人可能希望被通知项目已被处理(可能更新进度条,或更新系统的其他部分) , 随你)。 Let's put delegates aside for a second, and let's see how we can implement this using interfaces: 让我们把代表放在一边,让我们看看如何使用接口实现这一点:

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){}
}

Now say someone is consuming this class: 现在说有人正在消耗这个类:

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

So solve this problem, let's create an interface: 所以解决这个问题,让我们创建一个接口:

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

We can now refactor our original class: 我们现在可以重构我们原来的类:

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

and the consumer of your class can now do this: 而你班上的消费者现在可以这样做:

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(); 

Now that you understand that, you can think of delegates as mini interfaces, and you can then change your original class to this: 既然您已了解这一点,您可以将委托视为迷你接口,然后您可以将原始类更改为:

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

and the consumer: 和消费者:

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

To summarize, you can think of delegates as a way to provide outsiders a simple "hook" into your code to either let them provide small pieces of logic (think of Linq and filtering a collection) or for callbacks/events like I've demonstrated above. 总而言之,您可以将委托视为向外部人员提供一个简单的“钩子”到您的代码中的方式,以便让它们提供小块逻辑(想想Linq并过滤集合)或者像我已经演示过的回调/事件以上。

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

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