Answered by:
Understanding Delegate Code Sample

Question
-
Here is a code sample. I don't understand the following syntax in this sample. Can you please explain what is going on?
These are the lines I don't understand--particularly the bolded part. During edit mode these words are bolded new CalculationListener("List1").CalculationPrinter. But once i submit it, it is no longer bold. I don't understand why.
calc.AddListener(new CalculationListener("List1").CalculationPrinter);
calc.AddListener(new CalculationListener("List2").CalculationPrinter);
calc.AddListener(AlternateListener.CalculationCallback);I understand that the 3rd statement calc.AddListener(AlternateListener.CalculationCallback); uses a static method so that the method can be used without instantiating an object. So i understand the 3rd line. But the first two i do not. There are 2 reasons. 1) No object for CalculationListener was instantiated, thus NEW is being used within a method. The syntax seems strange. 2) CalculationListener("List1") is a contructor that accepts a string, and attached to it is a method that can be used by the delegate. In summary, it appears to me that this syntax is being used as a substitution for instantiation. How can i learn more about this syntax? It is very strange to me. thanks
using System; delegate void NotifyCalculation(int x, int y, int result); class Calculator { NotifyCalculation calcListener; public void AddListener(NotifyCalculation listener) { calcListener += listener; } public void RemoveListener(NotifyCalculation listener) { calcListener -= listener; } public int CalculateProduct(int num1, int num2) { // perform the calculation int result = num1 * num2; // notify the delegate that we have performed a calc calcListener(num1, num2, result); // return the result return result; } } class CalculationListener { private string idString; public CalculationListener(string id) { idString = id; } public void CalculationPrinter(int x, int y, int result) { Console.WriteLine("{0}: Notification: {1} x {2} = {3}", idString, x, y, result); } } class AlternateListener { public static void CalculationCallback(int x, int y, int result) { Console.WriteLine("Callback: {0} x {1} = {2}", x, y, result); } } class Listing_05 { static void Main(string[] args) { // create a new Calculator Calculator calc = new Calculator(); // create and add listeners calc.AddListener(new CalculationListener("List1").CalculationPrinter); calc.AddListener(new CalculationListener("List2").CalculationPrinter); calc.AddListener(AlternateListener.CalculationCallback); // perform a calculation calc.CalculateProduct(10, 20); // remove a listener calc.RemoveListener(AlternateListener.CalculationCallback); // perform a calculation calc.CalculateProduct(10, 30); // wait for input before exiting Console.WriteLine("Press enter to finish"); Console.ReadLine(); } }
- Edited by Jacob Pressures Tuesday, August 21, 2012 3:51 PM
Answers
-
1) No object for CalculationListener was instantiated, thus NEW is being used within a method. The syntax seems strange.
This isn't true - there is an object being instantiated. Basically, you're writing this:
CalculationListener temp = new CalculationListener("List1"); calc.AddListener(temp.CalculationPrinter);
Using "new CalculationListener("List1").CalculationPrinter is just a way to save some typing since you're only using that instance one time, to get the delegate.
2) CalculationListener("List1") is a contructor that accepts a string, and attached to it is a method that can be used by the delegate.
I recommend thinking about this differently. You're "Creating a CalculationListener instance from the constructor that accepts a string", then "Creating a delegate from that instance's CalculationPrinter method and passing it to the AddListener method".
If you look at the generated code, the above line really actually compiles into something like this:
// Create an instance of CalculationListener CalculationListener anInstance = new CalculationListener("List1"); // Create a delegate from the appropriate instance's method NotifyCalculation theDelegate = new NotifyCalculation(anInstance.CalculationPrinter); // Pass the delegate into the method calc.AddListener(theDelegate);
The compiler automatically "infers" the delegate type for you (creating the delegate from the method), so you don't have to type "new NotificationCalculation...", but this is actually what happens (effectively) in the resulting, compiled code. The above will function exactly the same as your one line version.
Does that help?
Reed Copsey, Jr. - http://reedcopsey.com
If a post answers your question, please click "Mark As Answer" on that post and "Mark as Helpful".- Marked as answer by Jacob Pressures Tuesday, August 21, 2012 8:29 PM
-
The expression
new SomeClass(parameters)
returns a new object.
You can store that object in a variable before calling a method on it:
SomeClass sc = new SomeClass(parameters); sc.SomeMethod();
but you are not required to.
You can also call the method on the newly created object:
new SomeClass(parameters).SomeMethod();
In your sample:
calc.AddListener(new CalculationListener("List1").CalculationPrinter);
new CalculationListener("List1") creates a new object of type CalculationListener and the CalculationPrinter member belonging to that new object is passed to AddListener.
That line is equivalent to:
CalculationListener listener = new CalculationListener("List1"); calc.AddListener(listener.CalculationPrinter);
The difference being that you don't keep a reference to the object anywhere.- Marked as answer by Jacob Pressures Tuesday, August 21, 2012 8:30 PM
-
Oh Reed, i did have an additional question from your post as well. How do you see the "generated code"?
Thanks! If you tell me the subject, I can google it and find the steps.
You can use Ildasm: http://msdn.microsoft.com/en-us/library/f7dy01k1(v=vs.100).aspx
It will turn your assembly (DLL or EXE) into the IL code that's generated so you can inspect what the compiler has done.
However, tools like .NET Reflector or JustDecompile will actually show you nice C# code instead of the IL that's generated.
Reed Copsey, Jr. - http://reedcopsey.com
If a post answers your question, please click "Mark As Answer" on that post and "Mark as Helpful".- Proposed as answer by Jason Dot Wang Thursday, August 23, 2012 5:22 AM
- Marked as answer by Jason Dot Wang Wednesday, August 29, 2012 8:28 AM
All replies
-
1) No object for CalculationListener was instantiated, thus NEW is being used within a method. The syntax seems strange.
This isn't true - there is an object being instantiated. Basically, you're writing this:
CalculationListener temp = new CalculationListener("List1"); calc.AddListener(temp.CalculationPrinter);
Using "new CalculationListener("List1").CalculationPrinter is just a way to save some typing since you're only using that instance one time, to get the delegate.
2) CalculationListener("List1") is a contructor that accepts a string, and attached to it is a method that can be used by the delegate.
I recommend thinking about this differently. You're "Creating a CalculationListener instance from the constructor that accepts a string", then "Creating a delegate from that instance's CalculationPrinter method and passing it to the AddListener method".
If you look at the generated code, the above line really actually compiles into something like this:
// Create an instance of CalculationListener CalculationListener anInstance = new CalculationListener("List1"); // Create a delegate from the appropriate instance's method NotifyCalculation theDelegate = new NotifyCalculation(anInstance.CalculationPrinter); // Pass the delegate into the method calc.AddListener(theDelegate);
The compiler automatically "infers" the delegate type for you (creating the delegate from the method), so you don't have to type "new NotificationCalculation...", but this is actually what happens (effectively) in the resulting, compiled code. The above will function exactly the same as your one line version.
Does that help?
Reed Copsey, Jr. - http://reedcopsey.com
If a post answers your question, please click "Mark As Answer" on that post and "Mark as Helpful".- Marked as answer by Jacob Pressures Tuesday, August 21, 2012 8:29 PM
-
The expression
new SomeClass(parameters)
returns a new object.
You can store that object in a variable before calling a method on it:
SomeClass sc = new SomeClass(parameters); sc.SomeMethod();
but you are not required to.
You can also call the method on the newly created object:
new SomeClass(parameters).SomeMethod();
In your sample:
calc.AddListener(new CalculationListener("List1").CalculationPrinter);
new CalculationListener("List1") creates a new object of type CalculationListener and the CalculationPrinter member belonging to that new object is passed to AddListener.
That line is equivalent to:
CalculationListener listener = new CalculationListener("List1"); calc.AddListener(listener.CalculationPrinter);
The difference being that you don't keep a reference to the object anywhere.- Marked as answer by Jacob Pressures Tuesday, August 21, 2012 8:30 PM
-
Both of these replies were EXTREMELY HELPFUL! You really helped me to demystify the code!!! thanks a million!
Louis, you explained that the "new SomeClass(parameters)" part returns an instance. I always wondered what each part did. When teaching instantiation everyone doesn't explain each part.
So what does this do? I've always been wondering which was the instance and what to call the following:
SomeClass sc;
Is this just a variable of type SomeClass? can you do anything with it?
Thanks guys! This was extremely helpful for me.
- Edited by Jacob Pressures Tuesday, August 21, 2012 7:57 PM
-
-
Oh Reed, i did have an additional question from your post as well. How do you see the "generated code"?
Thanks! If you tell me the subject, I can google it and find the steps.
You can use Ildasm: http://msdn.microsoft.com/en-us/library/f7dy01k1(v=vs.100).aspx
It will turn your assembly (DLL or EXE) into the IL code that's generated so you can inspect what the compiler has done.
However, tools like .NET Reflector or JustDecompile will actually show you nice C# code instead of the IL that's generated.
Reed Copsey, Jr. - http://reedcopsey.com
If a post answers your question, please click "Mark As Answer" on that post and "Mark as Helpful".- Proposed as answer by Jason Dot Wang Thursday, August 23, 2012 5:22 AM
- Marked as answer by Jason Dot Wang Wednesday, August 29, 2012 8:28 AM
-
So what does this do? I've always been wondering which was the instance and what to call the following:
SomeClass sc;
Is this just a variable of type SomeClass? can you do anything with it?
Yes, that's the declaration of a variable sc of type SomeClass. You can store a reference to that instance of SomeClass in it. You can them use members of the instance.
For example, the code
SomeClass sc = new SomeClass(parameters); sc.SomeMethod();
Line 1: creates an instance ('new') of type SomeClass, calling its constructor with parameter 'parameters' and stores a reference to that instance in the variable sc.
Line 2: call the method SomeMethod of the object referenced by the variable sc.