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

bra*_*ter 1 c# delegates compiler-errors function-pointers

当我尝试将成员函数(从SoundManager类)传递给委托(在EventManager中)时,我收到编译器错误.
错误:参数2:无法从'方法组'转换为'Event_Sharp.FunctionHandler'
代码:

public delegate void FunctionHandler(IEvent evnt);
Run Code Online (Sandbox Code Playgroud)

事件管理器::

public void RegisterListener(int type, FunctionHandler handler)
{
    // ...
}
Run Code Online (Sandbox Code Playgroud)

SoundManager.cs(构造函数):

EventManager.Instance.RegisterListener(Event_Bullet_Fired.GetType(), HandleBulletFired );
Run Code Online (Sandbox Code Playgroud)

其中HandleBulletFired是SoundManager的成员:

void HandleBulletFired(Event_Bullet_Fired evnt)
{
    // ...
}
Run Code Online (Sandbox Code Playgroud)

并且,Event_Bullet_Fired实现了IEvent接口.有人可以告诉我为什么我收到此错误以及为什么我不能使用HandleBulletFired作为委托?

Eri*_*ert 5

你正在做的不是类型安全,因此编译器抱怨.

想想这样:

interface IAnimal { }
class Lion : IAnimal { public void Roar() {} }
class Giraffe: IAnimal { }
delegate void D(IAnimal animal);
static void M(Lion lion) { lion.Roar(); }
Run Code Online (Sandbox Code Playgroud)

现在你说

D d = M;
Run Code Online (Sandbox Code Playgroud)

你明白为什么不行吗?因为什么都阻止你说

d(new Giraffe());
Run Code Online (Sandbox Code Playgroud)

现在你刚刚做了长颈鹿咆哮.或者说,你只是撞毁了CLR.

为防止您这样做,编译器会停止尝试进行不安全的分配.

请注意,您可以采用其他方式:

delegate void D2(Lion lion);
static void M2(IAnimal animal) {}
...
D2 d2 = M2;
Run Code Online (Sandbox Code Playgroud)

因为现在你要将狮子传递给d2,它会将IAnimal传递给M2,而狮子会保证实现IAnimal.

高调的方式是,委托转换的方法组在其参数类型中是逆变的,在返回类型中是协变的.

有关更多信息,请参阅我关于协方差和逆变的博客文章系列.