locked
How to pass a method as a constructor parameter

    Question

  • I have a Counter class that runs in parallel to the main form of my app. I want the counter to know the method in the main form to call when the counter stops or reaches 0. How do I pass the address of the method in the main form to the counter in C#? This would be fairly easy in C++.

    Or, would it be better to generate an event that is "sent" to the main form like

    somebutton.Click += new System.EventHandler(this.timer1_Tick);

    Can I do: counter.something += new System.EventHandler(this.counterhandler_method); ?

    Thanks.

    Wednesday, July 12, 2006 4:52 PM

Answers

  • Yes a delegate is nothing more than a function pointer.  Unlike C++ where it is notoriously difficult to pass class members as a function pointer in .NET it is automatically supported with no additional effort.  Therefore given the delegate of earlier you can do the following:

    public class StaticFoo
    {
       public static bool MyMethod ( string title, IntPtr handle )
       {
       }
    }

    public class Foo
    {
       public bool AnotherMethod ( string title, IntPtr handle )
       { }
    }

    //And later

    WindowEnumerator enumor = new WindowEnumerator();
    enumor.Enumerate(StaticFoo.MyMethod);

    Foo myInstance = new Foo();
    enumor.Enumerate(myInstance.AnotherMethod);

    Michael Taylor - 7/12/06

    Wednesday, July 12, 2006 5:48 PM
    Moderator

All replies

  • In most cases you should use an event on your counter class.  Suppose down the road that somebody other than the main form wanted to know when the counter was done.  Using an event it is simple. 

    However there are occasions when an event is not appropriate.  For example callback routines are normally not events.  If you enumerate the windows on the desktop you really only ever want one method called.  Using an event doesn't make sense here.  It does use the same implementation though.  You create a delegate that represents the method you want to call back.  In your constructor (or method or whatever) one of the parameters you request is of the delegate type.  The caller passes you the method through the delegate parameter and you invoke it when you want to.  Normally callbacks done in this manner use completely different names and arguments than events to avoid confusion.  For example normally the arguments the callback will receive are simply specified as parameters in the delegate definition rather than being contained in an -EventArgs derived class.  Here is an example of a class that might be used to enumerate all windows on the desktop.

    public delegate bool WindowEnumerateCallback ( string title, IntPtr handle );

    public sealed class WindowEnumerator
    {
       public void Enumerate ( WindowEnumerateCallback callback )
       {
          //For each window
             if (!callback(title, handle))
                break;
       }
    }

    Michael Taylor - 7/12/06

    Wednesday, July 12, 2006 5:09 PM
    Moderator
  • Thank you. I just read up on delegates and event handling, and I think I got it.

    However, I wasn't thinking of passing the form to the counter. I wanted to know how to pass an arbitrary method to the counter, no matter what class it is a member of. Is that kind of thing possible? Like passing a function pointer?

    Wednesday, July 12, 2006 5:39 PM
  • Yes a delegate is nothing more than a function pointer.  Unlike C++ where it is notoriously difficult to pass class members as a function pointer in .NET it is automatically supported with no additional effort.  Therefore given the delegate of earlier you can do the following:

    public class StaticFoo
    {
       public static bool MyMethod ( string title, IntPtr handle )
       {
       }
    }

    public class Foo
    {
       public bool AnotherMethod ( string title, IntPtr handle )
       { }
    }

    //And later

    WindowEnumerator enumor = new WindowEnumerator();
    enumor.Enumerate(StaticFoo.MyMethod);

    Foo myInstance = new Foo();
    enumor.Enumerate(myInstance.AnotherMethod);

    Michael Taylor - 7/12/06

    Wednesday, July 12, 2006 5:48 PM
    Moderator