泛型和事件

本文关键字:事件 泛型 | 更新日期: 2023-09-27 18:12:14

我正在制作一款游戏,我试图创造一种方法来处理对象之间的碰撞。我想这样做:

//Imaginary C#
public SomethingThatCollides()
{
    CollisionEvent<ObjectA> += CollisionWithObjA;
    CollisionEvent<ObjectB> += CollisionWithObjB;
}
void CollisionWithObjA(ObjectA other)
{
    //Do something
}
void CollisionWithObjB(ObjectB other)
{
    //Do something else
}

例如,当CollisionEvent<ObjectA>被触发时(可能是由一些冲突检查代码引起的),应该调用CollisionWithObjACollisionWithObjB也一样;当检测到与ObjectB的冲突时,它将引发CollisionEvent<ObjectB>事件,导致CollisionWithObjB被调用。

这样的事情可能吗?

泛型和事件

事情是这样的,如果class是泛型的并且它有静态字段,它可以像字典一样工作,key类型为

public class Something {
    public class EventsHolder<T> 
    {
       static event Action<T> CollideEvent;
    }
    public void AddEvent<T>(Action<T> collisionEvent) 
    {
      EventsHolder<T>.CollideEvent = collisionEvent;
    }
    public void RaiseCollision<T>(T Obj)
    {
      var Event = EventsHolder<T>.CollideEvent;
      if (Event != null) Event(Obj);
    }
}

缺点是它使用了不合适的静态字段。在这种情况下,您可以使用代码@Daniel张贴。

您无法真正创建这样的通用事件。我建议您创建一个特殊的事件参数类,它也封装了碰撞对象,并在事件处理程序方法中检查其类型:

public class CollisionEventArgs : EventArgs {
  public object Object {
    get; private set;
  }
  // ...
}

你需要一个特殊的调度方法来使用它:

class SomethingThatCollides {
  public SomethingThatCollides(CollisionManager cm) {
    cm.CollisionEvent += CollisionWithObj;
  }
  void CollisionWithObj(object sender, CollisionEventArgs args) {
    if (args.Object is ObjectA) {
      CollisionWithObjA((ObjectA)args.Object);
    }
    else if (args.Object is ObjectB) {
      CollisionWithObjB((ObjectB)args.Object);
    }
  }
  // ...
}

或者,您可以尝试使用双调度来解决这个问题,而不使用c#事件。查看wikipedia中的碰撞示例

那很丑,但是…您可以按类型拥有一个事件字典:

Dictionary<Type, object> MyEventsByType;
event Action<A> CollisionEventA;
event Action<B> CollisionEventB;
event Action<C> COllisionEventC;
void Initialize()
{
    MyEventsByType = new Dictionary<Type, object>();
    MyEventsByType.Add(typeof(A), CollisionEventA);
    MyEventsByType.Add(typeof(B), CollisionEventB);
    MyEventsByType.Add(typeof(C), CollisionEventC);
}
void RaiseCollision<T>(T Obj)
{
    Action<T> Event = (Action<T>)MyEventsByType[typeof(T)];
    if (Event != null) Event(Obj);
}