Ошибка компилятора при передаче функции-члена делегату - PullRequest
1 голос
/ 25 января 2011

Я получаю ошибку компилятора при попытке передать функцию-член (из класса 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 ]

5 голосов
/ 25 января 2011

То, что вы делаете, небезопасно, поэтому компилятор жалуется.

Думайте об этом так:

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;

потому что теперь вы собираетесь передать Льва в d2, который передаст IAnimal в M2, и Lion гарантированно реализует IAnimal.

Высокоэффективный способ сказать, что группа методов для делегирования преобразований является контравариантной в своих типах параметров и ковариантной в своих возвращаемых типах.

См. Мою серию статей в блоге о ковариации и контравариантности для получения дополнительной информации.

2 голосов
/ 25 января 2011

Может быть, вам стоит попытаться разыграть HandleBulletFired до FunctionHandler:

EventManager.Instance.RegisterListener(Event_Bullet_Fired.GetType(), (FunctionHandler)HandleBulletFired );
1 голос
/ 25 января 2011

Это не выглядит так Event_Bullet_Fired.GetType() возвращает int, поскольку RegisterListener метод требует:

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;
    // ...
}
...