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作为委托?
你正在做的不是类型安全,因此编译器抱怨.
想想这样:
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.
高调的方式是,委托转换的方法组在其参数类型中是逆变的,在返回类型中是协变的.
有关更多信息,请参阅我关于协方差和逆变的博客文章系列.