当我尝试将成员函数(从SoundManager类)传递给委托(在EventManager中)时,我收到编译器错误。
错误:参数2:无法从'方法组'转换为'Event_Sharp.FunctionHandler'
代码:
public delegate void FunctionHandler(IEvent evnt);
eventmanager进行::
public void RegisterListener(int type, FunctionHandler handler)
{
// ...
}
SoundManager.cs(构造函数):
EventManager.Instance.RegisterListener(Event_Bullet_Fired.GetType(), HandleBulletFired );
其中HandleBulletFired是SoundManager的成员:
void HandleBulletFired(Event_Bullet_Fired evnt)
{
// ...
}
和,Event_Bullet_Fired实现了IEvent接口。有人可以告诉我为什么我会收到此错误以及为什么我不能将HandleBulletFired用作代表?
答案 0 :(得分:5)
你所做的不是类型安全,因此编译器抱怨。
这样想:
interface IAnimal { }
class Lion : IAnimal { public void Roar() {} }
class Giraffe: IAnimal { }
delegate void D(IAnimal animal);
static void M(Lion lion) { lion.Roar(); }
现在你说
D d = M;
你知道为什么不起作用吗?因为没有什么能阻止你说
d(new Giraffe());
现在你刚刚做了长颈鹿咆哮。或者说,你只是撞毁了CLR。
为防止您这样做,编译器会停止尝试进行不安全的分配。
请注意,您可以走另一条路:
delegate void D2(Lion lion);
static void M2(IAnimal animal) {}
...
D2 d2 = M2;
因为现在你要将Lion传递给d2,它会将IAnimal传递给M2,并且Lion保证实现IAnimal。
高调的方式是,委托转换的方法组在其参数类型中是逆变的,在返回类型中是协变的。
有关更多信息,请参阅我关于协方差和逆变的博客文章系列。
答案 1 :(得分:2)
也许您应该尝试将HandleBulletFired
投射到FunctionHandler
:
EventManager.Instance.RegisterListener(Event_Bullet_Fired.GetType(), (FunctionHandler)HandleBulletFired );
答案 2 :(得分:1)
Event_Bullet_Fired.GetType()
看起来不像RegisterListener
方法那样返回int:
public void RegisterListener(int type, FunctionHandler handler)
<强>更新强>:
我认为错误的原因是Event_Bullet_Fired
更具体IEvent
。
在Event_Bullet_Fired
方法声明中尝试替换IEvent
到HandleBulletFired
:
void HandleBulletFired(IEvent evt)
{
Event_Bullet_Fired bullerFiredEvent = (Event_Bullet_Fired)evt;
// ...
}