Xenoprimate
Xenoprimate

Reputation: 7963

Using delegates with arguments

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.

Upvotes: 4

Views: 2018

Answers (3)

Mark Seemann
Mark Seemann

Reputation: 233367

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.

Upvotes: 0

bruno conde
bruno conde

Reputation: 48255

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

Upvotes: 5

David Hedlund
David Hedlund

Reputation: 129832

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

Upvotes: 2

Related Questions