4

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.

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 ....

Can someone please explain? Thanks so much!

Tizz
  • 820
  • 1
  • 15
  • 31
  • That example seems ... complicated. I would likely not write it like so, although I would need to know the larger context ;-) The "point" of a delegate (delegate/Action/Func), however, is that it *can* be invoked in a different context: e.g. as a callback. Instead, consider [`Regex.Replace(string,string,MatchEvaluator)`](http://msdn.microsoft.com/en-us/library/ht1sxswy%28v=vs.90%29.aspx), which shows a delegate (`MatchEvaluator`) being used in a *very* useful manner. (Ever tried to do a similar regex replacement in Java? It's not fun.) –  Feb 21 '12 at 20:08
  • Possible duplicate of http://stackoverflow.com/questions/2044301/what-is-delegate – cadrell0 Feb 21 '12 at 20:10
  • again though, couldn't you just do ... if(MatchEvaluator) Regex.Replace(string, string)? – Tizz Feb 21 '12 at 20:14

5 Answers5

4

The delegate is useful because it actually acts as a placeholder for any method that takes a string as parameter and returns void.

If you are familiar with C, it is similar to how a function pointer works. 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(array, new comparisonDelegate(compareDecreasing));
 SortArray(array, new comparisonDelegate(compareIncreasing));
Tudor
  • 61,523
  • 12
  • 102
  • 142
  • Your example doesn't define any `compareIncreasing` methods and instead you have two identical signatures for `compareDecreasing`... ;) – Nuffin Feb 21 '12 at 20:39
3

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.

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.

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. 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. 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.

Say we want to see how many strings start with "E", we could just use:

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...

Reed Copsey
  • 554,122
  • 78
  • 1,158
  • 1,373
1

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. 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.

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

Robert Harvey
  • 178,213
  • 47
  • 333
  • 501
0

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.

Chris Farmer
  • 24,974
  • 34
  • 121
  • 164
0

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.

BFree
  • 102,548
  • 21
  • 159
  • 201