Tutorial :Using delegates with arguments



Question:

I have a class 'KeyEvent'; one of which's members is:

public delegate void eventmethod(object[] args);  

And the method passed to the object in the constructor is stored in this member:

private eventmethod em;  

Constructor:

  public KeyEvent(eventmethod D) {     em = D;    }    public KeyEvent(eventmethod D, object[] args) : this(D) {     this.args = args;    }    public KeyEvent(Keys[] keys, eventmethod D, object[] args) : this(keys, D) {     this.args = args;    }  

The 'eventmethod' method is then called by using the public method "ThrowEvent":

  public void ThrowEvent() {     if (!repeat && thrown) return;     em.DynamicInvoke(args);     this.thrown = true;    }  

As far as I can see, this compiles fine. But when trying to create an instance of this class (KeyEvent), I'm doing something wrong. This is what I have so far:

   object[] args = {new Vector2(0.0f, -200.0f)};     Keys[] keys = { Keys.W };     KeyEvent KeyEvent_W = new KeyEvent(keys, new KeyEvent.eventmethod(GameBase.ChangeSquareSpeed), args);  

GameBase.ChangeSquareSpeed doesn't do anything at the moment, but looks like this:

  static public void ChangeSquareSpeed(Vector2 squarespeed) {      }  

Anyway, the erroneous line is this one:

KeyEvent KeyEvent_W = new KeyEvent(keys, new KeyEvent.eventmethod(GameBase.ChangeSquareSpeed), args);  

The error that the compiler gives me is:

error CS0123: No overload for 'ChangeSquareSpeed' matches delegate 'BLBGameBase.KeyEvent.eventmethod'

My question is: Does this mean I have to change ChangeSquareSpeed to take no parameters (in which case, what is a better way of doing this?), or am I doing something syntactically wrong?

Thank you in advance.


Solution:1

I think the error is very explicit. Your ChangeSquareSpeed method doesn't match the delegate . The delegate expects a method with one object[] as parameter but your passing a method with a Vector2 as a parameter, hence the error.

Try this method:

static public void ChangeSquareSpeed(object[] squarespeed)   {}  

(update)

I see some confusion in your code, specially in the line:

object[] args = {new Vector2(0.0f, -200.0f)};  

I can't really understand if you want an array of Vector2's or just a Vector2's object.

If you pretend to have an array of Vector2's I think this might seem reasonable:

Change the delegate to:

public delegate void eventmethod(Vector2 args);  

and then

public void ThrowEvent() {     if (!repeat && thrown) return;     foreach(object obj : args)     {        em.DynamicInvoke((Vector2)obj);     }     this.thrown = true;  }  

(update 2)

In that case, I think you should create a generic version of KeyEvent. See this example and go from there:

    class KeyEvent<T>      {          public T Args { get; set; }          public Action<T> A { get; set; }            public KeyEvent() { }            public void ThrowEvent()          {              A.DynamicInvoke(Args);          }      }        // ...        static void M1(object[] o)      {          Console.WriteLine("M1 {0}", o);      }        static void M2(Vector2 v)      {          Console.WriteLine("M2 {0}", v);      }        static void Main(string[] args)      {          KeyEvent<object[]> e1 = new KeyEvent<object[]>          {              A = new Action<object[]>(M1),             Args = new object[] {};          };          KeyEvent<Vector2> e2 = new KeyEvent<Vector2>          {             A = new Action<Vector2>(M2),             Args = new Vector2();          };      }  


Solution:2

The delegate eventmethod states that all events using it should take object[] (args) as their only in parameter. Depending on what you're using this code for, you want to either:

  • Change the signature of ChangeSquareSpeed to ChangeSquareSpeed(object[] squarespeed)
  • Create a new delegate, with the signature void neweventmethod(Vector2 args); and use that
  • Change the signature of eventmethod to the above


Solution:3

If you are on C# 3, change the delegate to an Action<object[]>. That will make your life much simpler, as it will be type-safe to invoke it.

That would allow you to simply invoke it like this:

this.em(args);  

and you would have compile-time checking instead.


Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Previous
Next Post »