我在玩游戏只是为了娱乐,我试图实现事件,但出现错误:


  错误CS0305:使用通用类型'Game.NPC.Events.MurderEventArgs'需要2个类型参数(CS0305)(游戏)


引发事件的代码:

public event EventHandler<EventArgs> OnMurderEvent;

public void RaiseMurderEvent<TVictim, TMurderer>(TVictim npcVictim, TMurderer npcMurderer)
{
    if (OnMurderEvent != null)
    {
        OnMurderEvent(this, new MurderEventArgs<TVictim, TMurderer>(npcVictim, npcMurderer));
    }
}


我正在处理事件的代码:

npc.OnMurderEvent += HandleMurderEvent;
npc.RaiseMurderEvent<Victim, Murderer>(null, null);

static void HandleMurderEvent(object sender, EventArgs e)
{
    Console.WriteLine((MurderEventArgs)e);
}


强制转换因为没有通用类型而无法使用,有人可以帮忙吗?

最佳答案

假设您的MurderEventArgs看起来像这样:



class MurderEventArgs<TVictim, TMurderer> : EventArgs
{
    public MurderEventArgs(TVictim victim, TMurderer murderer)
    {
        //your code here
    }
}


您可以将EventHandler更改为:



class EventRaiser<TVictim, TMurderer>
{
    public event EventHandler<MurderEventArgs<TVictim, TMurderer>> OnMurderEvent;

    public void RaiseMurderEvent(TVictim npcVictim, TMurderer npcMurderer)
    {
        if (OnMurderEvent != null)
        {
            OnMurderEvent(this, new MurderEventArgs<TVictim, TMurderer>(npcVictim, npcMurderer));
        }
    }
}


您的用法如下所示:



static void FireAndForget<TVictim, TMurderer>(TVictim victim, TMurderer murderer)
{
    var npc = new EventRaiser<TVictim, TMurderer>();
    npc.OnMurderEvent += HandleMurderEvent<TVictim,TMurderer>;
    npc.OnMurderEvent += HandleMurderEventAlt;
    npc.RaiseMurderEvent(victim, murderer);
}

static void HandleMurderEvent<TVictim, TMurderer>(object sender, EventArgs e)
{
    var murderEvent = (MurderEventArgs<TVictim, TMurderer>)e;
    //do something with the event
}

//or alternatively
static void HandleMurderEventAlt<TVictim, TMurderer>(object sender, MurderEventArgs<TVictim, TMurderer> e)
{
    //do something with the event
}


一些事后思考

我将其命名为FireAndForget是有原因的。您需要为EventRaiserTVictim的每种类型组合创建一个新的TMurderer实例,或将现有实例重新用于组合。但这在我看来违反了EventListener的目的。

您也可以创建一个public void Murder<TVictim, TMurderer>(TVictim victim, TMurderer murderer)方法,然后在其中进行处理。完全不需要任何事件。缺点:需要强制TMurderer调用该方法。

或在任何MurdererBy<TMurderer>(TMurderer murderer)类上实现TVictim并引发MurderedByEvent。缺点:TVictim“知道” TMurderer。让TMurderer实现一个Murders<TVictim>(TVictim victim)方法,但谁强制谋杀被登记?

或创建某种LifeCycleManager,TVictim只能由该Manager创建(工厂模式)。在创建每个实例时,管理器都会将其自己的EventListener注册到新TVictim实例的MurderedByEvent中。

摘要

我上面的示例代码在某种程度上回答了您的问题,但是您应该重新考虑模型。谁需要知道事件?是否应该知道每起谋杀案?受害人会怎样?

谋杀事件需要知道什么?受害者和凶手的名字才和其他作者提出的接口模型一起使用。

09-27 17:44