views:

94

answers:

3

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.

+3  A: 

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();
        };
    }
bruno conde
In this case however, how will I use the object passed to squarespeed as a vector? I only ever want to use a Vector2 in ChangeSquareSpeed - is there no better way?
Motig
@Motig, see my update. I can't really tell if you want an array of Vector2's or just a Vector2's object as argument to KeyEvent.
bruno conde
Mm, this would be suitable, but I need the delegate eventmethod to be flexible. In this instance, I am using it to pass a Vector2, but I may also pass it anything else, depending on what exactly the 'event' to be called is.
Motig
@Motig, please see my update2.
bruno conde
+2  A: 

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
David Hedlund
A: 

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.

Mark Seemann
Go with the delegate Action<object[]> instead of Func. Func uses the first generic as a return type; it's not a parameter type. Action returns void, so all generic types listed are argument types.
Cylon Cat
That is correct - thanks for pointing that out. Updated the answer.
Mark Seemann