But this is what confused me! I don't quite understand what we are doing here.
What I can say is that we are converting param1 value to a double. I don't understand what the input, substring and the values in the parameters are doing. I think knowing what the 'commaPos' did would be useful - but can someone explain?
The word "delegate" is actually used in two slightly different ways. First, a delegate can be a type, just as a class is a type. Like classes, delegates are reference types, i.e. a variable of that type contains a reference to an object rather than an object itself. Just as you create instances of classes, so you create instances of a delegates and those objects are also referred to as delegates. That means that a delegate object is an instance of a delegate type.
A delegate object is an object that contains a reference to a method. The idea is that you can create a delegate to a method and then pass that object around like you would any other object. You can then invoke the delegate to execute the method it refers to in places that would normally not have access to it because they aren't aware of the object that the method is a member of. For instance, the List<T> class has an overload of its Sort method that accepts a Comparison<T> delegate. The Comparison<T> delegate is defined as taking two objects of type T and returning an int that indicates their relative order. You can then write a method in a form that takes two objects of a particular type and returns an int that indicates their relative order, create a Comparison<T> delegate for that method and then pass it to the Sort method of a List<T>. That List is then able to invoke your method for the purposes of sorting, even though it doesn't know that your form exists.
declares the delegate type. 'processDelegate' is now a type that can refer to any method that has two 'double' parameters and a return type of 'double'. The delegate type says nothing about how such methods should be implemented. The next two lines:
declare two methods with signatures that match the 'processDelegate' type. That means that you can create instances of the 'processDelegate' type that refer to either of those methods. The first method multiplies the two parameters together and returns the result and the second method divides the first parameter by the second and returns the result. They could be written long-hand like this:
The next three lines have exactly zero to do with delegates. They would simply be part of an example that shows how to use the delegate and methods above. This code:
is simply extracting two doubles to use as arguments to the methods above. The input would be a single string that contains two numbers separated by a comma, e.g. "9.3,3.1". The code will then convert that to the double values 9.3 and 3.1, ready to be passed to 'processDelegate' instances that refer to your Multiply and Divide methods. The subsequent code would presumably do that, e.g.
var multiplier = new processDelegate(Multiply);
var divider = new processDelegate(Divide);
var product = multiplier(param1, param2);
var quotient = divider(param1, param2);
After that code, 'product' would contain 28.83 and quotient would contain 3.0. The code creates delegates that refer to the two methods and then invokes the delegates. Internally the delegate will call the method it refers to, passing in its own parameters as argument. That code is basically equivalent to this:
var product = Multiply(param1, param2);
var quotient = Divide(param1, param2);
It has no specific advantage over that in this particular case but, as I said, you could, if you wanted to, pass those delegates around and then invoke them somewhere that has no direct access to the Multiply and Divide methods.
A note on naming delegates now. Microsoft recommends that delegates NOT be suffixed with 'Delegate'. You'll find that throughout the .NET Framework, e.g. Comparison<T>, Action, Func, etc, etc. If everyone can use those types successfully without a suffix, you can live without a suffix on your own delegates. Also, EVERY type name should begin with an upper-case letter. That means that Process would be a better name than 'processDelegate'.
Also, unless it's use implies something specific, there's no point to declaring your own delegate types. For instance, the Comparison<T> delegate DOES imply something specific, i.e. the two arguments are to be compared and the result is to indicate their relative order. In most cases, you should just use an Action or a Func. Action delegates can have up to 16 parameters of any type and do not return anything while Func delegates can also have 16 parameters and do return something. In your case above, you could have used a Func<double, double, double>, although doing so would not have taught you how to declare delegate types.
I saw your answer this morning and I wanted to wait until I could really sit down and absorb the information that you were sharing. I have mad lots of notes in the IDE next to the code and I can look back at them.
You have a flair in teaching. The points that you were making were all very easily understood and they followed each other very well.
Thank you for your very detailed answer - I appreciate you taking the time to write a reply as good as this.
This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
By continuing to use this site, you are consenting to our use of cookies.