Использование делегатов с аргументами - PullRequest
4 голосов
/ 06 января 2010

У меня есть класс 'KeyEvent'; один из членов которого:

public delegate void eventmethod(object[] args);

И метод, переданный объекту в конструкторе, сохраняется в этом члене:

private eventmethod em;

Конструктор:

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

Затем вызывается метод eventmethod с помощью открытого метода ThrowEvent:

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

Насколько я вижу, это прекрасно компилируется. Но при попытке создать экземпляр этого класса (KeyEvent) я что-то делаю не так. Это то, что я до сих пор:

   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 ​​в данный момент ничего не делает, но выглядит так:

  static public void ChangeSquareSpeed(Vector2 squarespeed) {

  }

В любом случае, ошибочная строка - это:

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

Ошибка, которую дает мне компилятор:

ошибка CS0123: нет перегрузки для 'ChangeSquareSpeed', соответствует делегату 'BLBGameBase.KeyEvent.eventmethod'

У меня вопрос: означает ли это, что я должен изменить ChangeSquareSpeed, чтобы он не принимал никаких параметров (в таком случае, как лучше это сделать?), Или я делаю что-то синтаксически неправильно?

Заранее спасибо.

Ответы [ 3 ]

4 голосов
/ 06 января 2010

Я думаю, что ошибка очень явная. Ваш ChangeSquareSpeed метод не соответствует делегату. Делегат ожидает метод с одним object[] в качестве параметра, но вы передаете метод с Vector2 в качестве параметра, следовательно, ошибка.

Попробуйте этот метод:

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

(обновление)

Я вижу некоторую путаницу в вашем коде, особенно в строке:

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

Я не могу понять, хотите ли вы массив Vector2 или просто объект Vector2.

Если вы притворяетесь, что у вас есть массив Vector2, я думаю, это может показаться разумным:

Измените делегата на:

public delegate void eventmethod(Vector2 args);

, а затем

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

(обновление 2)

В этом случае, я думаю, вам следует создать общую версию KeyEvent. Посмотрите этот пример и перейдите оттуда:

    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();
        };
    }
2 голосов
/ 06 января 2010

Делегат eventmethod утверждает, что все события, использующие его, должны принимать object[] (аргументы) в качестве единственного параметра.В зависимости от того, для чего вы используете этот код, вы можете:

  • Изменить подпись ChangeSquareSpeed на ChangeSquareSpeed(object[] squarespeed)
  • Создать новый делегат с подписьюvoid neweventmethod(Vector2 args); и используйте это
  • Измените подпись eventmethod на указанную выше
0 голосов
/ 06 января 2010

Если вы находитесь на C # 3, измените делегата на Action<object[]>. Это сделает вашу жизнь намного проще, так как будет безопасно вызывать ее.

Это позволит вам просто вызвать его так:

this.em(args);

и вместо этого у вас будет проверка во время компиляции.

...