泛型和事件
本文关键字:事件 泛型 | 更新日期: 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>
被触发时(可能是由一些冲突检查代码引起的),应该调用CollisionWithObjA
。CollisionWithObjB
也一样;当检测到与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);
}