Рассмотрим следующий код:
abstract class Foo<T>
where T : Foo<T>, new()
{
void Test()
{
if(Bar != null)
Bar(this);
}
public event Bar<T> Bar;
}
delegate void Bar<T>(T foo)
where T : Foo<T>, new();
Строка Bar(this)
приводит к следующему компилятору Ошибка:
Тип аргумента Foo <T> не присваивается типу параметра T
T ограничивается Foo <T> так как я хочу, чтобы производные классы в основном указывали базовому классу свой тип, чтобы этот тип можно было использовать в обратном вызове события, чтобы сохранить разработчику от необходимости передавать аргумент обратного вызова производному типу.
Я вижу, что код работает не очень хорошо, но у меня есть немного блокировки относительно того, как это сделать правильно, не заканчивая общим делегатом, который можно использовать для любой старой вещи. Я также не совсем уверен, почему ограничение T не создает ошибку компилятора, считая ее рекурсивной.
ИЗМЕНИТЬ
Мне нужно прояснить это, я думаю! Вот новый пример, который, надеюсь, будет намного яснее. Обратите внимание, что обработчик события OnDuckReady
ниже генерирует ошибку компилятора.
Как мне передать событие в правильном типе?
abstract class Animal<T>
where T : Animal<T>, new()
{
void Test()
{
if(AnimalReady != null)
AnimalReady(this);
}
public event AnimalHandler<T> AnimalReady;
}
delegate void AnimalHandler<T>(Animal<T> animal)
where T : Animal<T>, new();
class Duck : Animal<Duck>
{
public void FlyAway()
{
}
}
class Test
{
void Main()
{
Duck duck = new Duck();
duck.AnimalReady += OnDuckReady; // COMPILER ERROR
}
void OnDuckReady(Duck duck)
{
duck.FlyAway();
}
}