Проблема в том, что вы пытаетесь использовать дисперсию неправильно.
Идея отклонения состоит в том, что если вашему методу не нужна такая конкретная информация, которую, как говорит делегат, он предоставит, и если ваш метод возвращает больше конкретной информации, чем должен вернуть делегат, то вы все в порядке, чтобы построить делегат, используя этот метод.
В вашем случае все наоборот:
public delegate void StatisticsDelegate(object sender, EventArgs e);
static void BowlerStatistics(object sender, BallThrownEventArgs e)
BowlerStatistics
имеет для получения BallThrownEventArgs
, но StatisticsDelegate
только гарантирует, что он даст EventArgs
.
Предположим, вы можете создать StatisticsDelegate
из BowlerStatistics
: что вы ожидаете от следующего кода?
StaticticsDelegate del = BowlerStatistics;
del(null, new EventArgs());
BowlerStatistics
не будет иметь никакой связанной с мячом информации для работы.
Или использовать существующий код, но немного переместить его:
StaticticsDelegate del = BowlerStatistics; // *
RunsScoredEventArgs re = new RunsScoredEventArgs("Skeet", 55);
del(DynamicDelegates.Main, re);
del = BatsmanStatistics; // *
BallThrownEventArgs be = new BallThrownEventArgs(90, 145);
del(DynamicDelegates.Main,be);
Console.ReadLine();
На этот раз вы пытаетесь заставить представителя статистики боулера справиться со статистикой игрока с битой и наоборот! Единственные строки, которые не могут быть скомпилированы, - это группы преобразования групп методов (помеченные // *
выше), поэтому для обеспечения безопасности типов они не компилируются.
Ковариантность и контравариантность - сложные темы - вы можете найти серию сообщений Эрика Липперта в блоге полезной. До C # 4 дисперсия применяется только к созданию делегатов; Начиная с C # 4 также есть интерфейс и делегат универсальная дисперсия , позволяющая написать:
// Covariance
IEnumerable<string> strings = new List<string>();
IEnumerable<object> objects = strings;
// Contravariance
Comparer<Shape> areaSorter = (s1, s2) => s1.Area.CompareTo(s2.Area);
Comparer<Triangle> triangleAreaSorter = areaSorter;