将成员函数传递给委托时的编译器错误

时间:2011-01-24 23:07:08

标签: c# delegates compiler-errors function-pointers

当我尝试将成员函数(从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用作代表?

3 个答案:

答案 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方法声明中尝试替换IEventHandleBulletFired

void HandleBulletFired(IEvent evt)
{
    Event_Bullet_Fired bullerFiredEvent = (Event_Bullet_Fired)evt;
    // ...
}