Noobie C # delegate basics

I don’t think I understand the meaning of the delegate method. All the examples I've 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 don’t understand why this is necessary when you simply can just implement getListStrings () and iterate through the lines yourself, doing what you need to do as if it were a delegate.

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

Private members don't make sense, because I can 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 getListStrings ().

Can someone explain? Many thanks!

+4
source share
5 answers

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, this is similar to how a function pointer works. Instead, you can pass any method that matches the type of signature and return.

For example, let's say I want to implement a method that sorts a group of objects. In addition to the list of objects, I can also pass in a delegate that indicates how sorting will be done. Since any method corresponding to the delegate can be passed, I can then dynamically switch between different methods if I want to, for example, reduce or increase the 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)); 
+4
source

I don’t understand why this is necessary when you simply can just implement getListStrings () and iterate over the lines yourself, doing what you need to do as if it were a delegate.

The goal is to create a function that will work with the collection, but perform any operation.

This is easier to understand with an 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 lines have more than 4 characters - the Enumerable.Count method has an overload that accepts a delegate - the predicate Func<T,bool> , which you can use. This allows you to specify any operation and count the elements, i.e.

 List<string> listOfStrings = GetListOfStrings(); int countOfStringsGreaterThanFourChars = listOfStrings.Count(s => s.Length > 4); 

Here we pass a delegate (created using a lambda expression) that gives us our criteria. Having the Count method, which the delegate accepts, it works for any criteria, so we don’t need to redefine it every time we want a different condition.

Let's say we want to see how many lines begin with "E", we could just use:

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

Again, we need to write code that is relevant to our specific need, and not duplicate all the boilerplate code that we need to scroll through our collection and count the elements ...

+3
source

Using the delegate in the illustration allows you to change the implementation of the method.

A better example is the Comparer method. I will not enter the IComparer interface, but suffice it to say that using a delegate, you can change the behavior of the sort method by passing the comparison function delegate to it.

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

+1
source

First, it allows you to enter different types of behavior with the same method signature. In one case, you can simply add to your list. Otherwise, you can add to the list and write to the log file or something else that you might want to do in DoSomethingToStringsDelegate .

0
source

Think about it in terms of events. Suppose you have a class that does some processing in the list of elements, and for each element, someone consuming your class may be notified that the element has been processed (perhaps update the progress bar or update some other part of the system , no difference). Let's put the delegates aside for a second and 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 that 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, create an interface:

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

Now we can reorganize 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 this, you can think of delegates as mini-interfaces, and then you can change your 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.Callback != null) { this.Callback(item); } } } private void ProcessItem(string item){} public Action<string> Callback {get;set;} } 

and 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 how to give outsiders a simple “hook” to your code, to allow them to provide small pieces of logic (think about Linq and filtering the collection) or for callbacks / events like I’ve demonstrated above .

0
source

Source: https://habr.com/ru/post/1397665/


All Articles