C# 使用带参数的委托

C# 使用带参数的委托,c#,delegates,arguments,C#,Delegates,Arguments,我有一门“关键事件”课;其成员之一是: 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 = arg

我有一门“关键事件”课;其成员之一是:

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;
  }
然后使用公共方法“ThrowEvent”调用“eventmethod”方法:

据我所知,这本书编写得很好。但是当试图创建这个类的实例(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) {

  }
this.em(args);
无论如何,错误的路线是:

KeyEvent KeyEvent_W = new KeyEvent(keys, new KeyEvent.eventmethod(GameBase.ChangeSquareSpeed), args);
编译器给我的错误是:

错误CS0123:“ChangeSquareSpeed”没有重载与委托“BLBGameBase.KeyEvent.eventmethod”匹配

我的问题是:这是否意味着我必须更改ChangeSquareSpeed以不获取任何参数(在这种情况下,什么是更好的方法?)


提前谢谢。

我认为错误很明显。您的
ChangeSquareSpeed
方法与委托不匹配。代理希望一个方法使用一个
对象[]
作为参数,但您传递的方法使用
向量2
作为参数,因此会出现错误

尝试以下方法:

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

我看到您的代码有些混乱,特别是在以下行:

object[] args = {new Vector2(0.0f, -200.0f)};
我真的不明白您是想要一个
Vector2
数组,还是仅仅想要一个
Vector2
对象

如果你假装有一个向量2的数组,我认为这似乎是合理的:

将委托更改为:

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();
        };
    }
class键事件
{
公共T参数{get;set;}
公共操作A{get;set;}
公钥事件(){}
公共void ThrowEvent()
{
A.DynamicInvoke(Args);
}
}
// ...
静态空隙M1(对象[]o)
{
Console.WriteLine(“M1{0}”,o);
}
静态空隙M2(矢量2 v)
{
Console.WriteLine(“M2{0}”,v);
}
静态void Main(字符串[]参数)
{
KeyEvent e1=新的KeyEvent
{ 
A=新动作(M1),
Args=新对象[]{};
};
KeyEvent e2=新的KeyEvent
{
A=新动作(M2),
Args=新向量2();
};
}

委托
eventmethod
声明所有使用它的事件都应将
对象[]
(args)作为其唯一的in参数。根据您使用此代码的目的,您希望:

  • ChangeSquareSpeed
    的签名更改为
    ChangeSquareSpeed(object[]squarespeed)
  • 使用签名
    void neweventmethod(Vector2参数)创建一个新委托并使用它
  • eventmethod
    的签名更改为上述内容
如果您在C#3上,请将代理更改为
操作。这将使您的生活更加简单,因为调用它将是类型安全的

这将允许您像这样简单地调用它:

  static public void ChangeSquareSpeed(Vector2 squarespeed) {

  }
this.em(args);

您可以使用编译时检查。

但是,在这种情况下,如何使用传递给squarespeed的对象作为向量?我只想在ChangeSquareSpeed中使用Vector2-没有更好的方法吗?@Motig,查看我的更新。我真的不知道你是想要一个Vector2数组还是仅仅一个Vector2对象作为KeyEvent.Mm的参数,这是合适的,但我需要委托eventmethod是灵活的。在本例中,我使用它来传递一个向量2,但也可以传递任何其他内容,这取决于要调用的“事件”的确切内容。使用委托操作而不是Func。Func使用第一个泛型作为返回类型;它不是参数类型。操作返回void,所以列出的所有泛型类型都是参数类型。这是正确的-感谢您指出这一点。更新了答案。