我正在玩游戏只是为了好玩,我试图实现事件,但我收到了错误:
错误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);
}
由于它没有通用类型,因此无法工作?
答案 0 :(得分:1)
我不完全确定没有看到更多的代码,但因为它看起来像类型params TVictim,第二个代码片段的TMurderer对应于具体类型Victim,Murderer那么也许你的第二个片段只需要改变以下内容:
npc.OnMurderEvent += HandleMurderEvent;
npc.RaiseMurderEvent<Victim, Murderer>(null, null);
static void HandleMurderEvent(object sender, EventArgs e)
{
Console.WriteLine((MurderEventArgs<Victim, Murderer>)e);
}
在回复您的评论时,要删除泛型(这似乎是大多数人在此推荐的内容),您可以将MurderEventArgs更改为:
public class MurderEventArgs : EventArgs
{
public MurderEventArgs(IPerson victim, IPerson murderer)
{
Victim = victim;
Murderer = murderer;
}
public IPerson Victim { get; }
public IPerson Murderer { get; }
}
在举起事件的地方,它会是:
public event EventHandler<MurderEventArgs> OnMurderEvent;
public void RaiseMurderEvent(IPerson npcVictim, IPerson npcMurderer)
{
if (OnMurderEvent != null)
OnMurderEvent(this, new MurderEventArgs(npcVictim, npcMurderer));
}
在IPerson界面中会有一些常见信息,然后在专门的实现中会有更多信息 -
public interface IPerson
{
string Name { get; }
}
public abstract class Person : IPerson
{
protected Person (string name)
{
Name = name;
}
public string Name { get; }
}
public class Adult : Person
{
public Adult(string name) : base(name) { }
}
public class Child : Person
{
public Child(string name, int age) : base(name)
{
Age = age
}
public int Age { get; }
}
最后,事件监听代码将是这样的:
npc.OnMurderEvent += Npc_OnMurderEvent;
npc.RaiseMurderEvent(victim, murderer);
private static void Npc_OnMurderEvent(object sender, MurderEventArgs e)
{
Console.WriteLine(e.Victim.Name + " was murdered by " + e.Murderer.Name);
var murdererAsChild = e.Murderer as Child;
if (murdererAsChild != null)
Console.WriteLine(".. who is only a child, it must be Damien!");
// Deal with any other special cases for particular Victim, Murderer combinations..
}
正如你在评论@ romain-aga(我无耻地从中偷走了IPerson接口名称)的回答时所说的那样,如果你对凶手或者更多的受害者感兴趣,就必须执行运行时转换。特定类型。
答案 1 :(得分:0)
使用接口,您可以获得解决方法。
如果您的课程:博士,学生,教师等...从同一个界面/班级实施或继承,您可以写下:
public event EventHandler<MurderEventArgs> OnMurderEvent;
public void RaiseMurderEvent(IPerson npcVictim, IPerson npcMurderer)
{
if (OnMurderEvent != null)
{
OnMurderEvent(this, new MurderEventArgs(npcVictim, npcMurderer));
}
}
并且这样做:
npc.OnMurderEvent += HandleMurderEvent;
npc.RaiseMurderEvent(null, null);
static void HandleMurderEvent(object sender, MurderEventArgs e)
{
Console.WriteLine(e);
}
对于您的类层次结构,您可以使用类似的东西:
public interface IPerson
{
// All the methods/properties that make a person
}
public abstract class Person : IPerson
{
// All the common implementations
}
public class Doctor/Student/Teacher/etc... : Person
{
// All the specific implementations
}
答案 2 :(得分:0)
假设您的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
是有原因的。您需要为EventRaiser
和TVictim
的每种类型组合创建一个新的TMurderer
实例,或者重复使用已存在的实例进行组合。但在我看来,这违背了EventListener的目的。
您也可以创建一个public void Murder<TVictim, TMurderer>(TVictim victim, TMurderer murderer)
方法并在那里完成您的工作。根本不需要活动。缺点:需要强制TMurderer
调用该方法。
或者在任何MurdererBy<TMurderer>(TMurderer murderer)
课程中实施TVictim
并举起 MurderedByEvent 。缺点:TVictim
&#34;知道&#34; TMurderer
。让TMurderer
实施一个Murders<TVictim>(TVictim victim)
方法,但是谁强制执行谋杀?
或者创建某种 LifeCycleManager ,TVictim
只能由该管理器创建(工厂模式)。在每个实例创建时,Manager将自己的EventListener注册到新TVictim
实例的 MurderedByEvent 。
我上面的示例代码在某种程度上回答了您的问题,但您应该重新思考您的模型。谁需要知道这个事件?每个谋杀案都应该知道吗?受害者会怎么样?
谋杀事件需要知道什么?受害者和凶手的姓名只能使用其他作者提出的界面模型。