none
Understanding Delegate Code Sample RRS feed

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


    Tuesday, August 21, 2012 3:49 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".

    Tuesday, August 21, 2012 4:22 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.
    Tuesday, August 21, 2012 4:25 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
    Tuesday, August 21, 2012 8:05 PM

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

    Tuesday, August 21, 2012 4:22 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.
    Tuesday, August 21, 2012 4:25 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.


    Tuesday, August 21, 2012 7:56 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.

    Tuesday, August 21, 2012 8:03 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
    Tuesday, August 21, 2012 8:05 PM
  • 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.

    Wednesday, August 22, 2012 7:26 AM