Прежде всего, чтобы ответить на некоторые вопросы в комментариях к вопросу: я обычно настойчиво отвечаю на вопросы «почему нет», потому что трудно найти краткие причины, по которым все в мире решили не выполнять эту работу , а поскольку вся работа не выполняется по умолчанию .Скорее, вам нужно найти причину для выполнения работы и отнять ресурсы у другой работы , которые менее важны для ее выполнения.
Более того, вопросы «почему нет» этой формы, в которых задаются вопросы о мотивации и выборе людей, работающих в конкретной компании, могут быть подотчетны только тем людям, которые приняли это решение, которых, вероятно, здесь нет.
Однако в этом случае мы можем сделать исключение из моего общего правила закрытия вопросов «почему нет», потому что вопрос иллюстрирует важный момент о ковариации делегатов, о котором я никогда раньше не писал.
Я не принял решение оставить делегатов событий неизменными, но если бы я был в состоянии сделать это, я бы оставил делегатов событий неизменными по двум причинам.
Первый - это просто пункт «поощрять передовой опыт».Обработчики событий, как правило, специально создаются для обработки определенного события, и я не знаю, по какой веской причине, чтобы сделать его проще, чем уже есть, использовать делегатов, которые имеют несовпадения в сигнатуре, в качестве обработчиков, даже если эти несоответствия могут бытьиметь дело с помощью дисперсии.Обработчик событий, который точно соответствует во всех отношениях событию, которое он должен обрабатывать, дает мне больше уверенности в том, что разработчик знает, что он делает, при построении событийного процесса.
Это довольно слабая причина.Более сильная причина также является более грустной.
Как мы знаем, универсальные типы делегатов можно сделать ковариантными в их типах возвращаемых значений и контравариантными в их типах параметров;мы обычно думаем о дисперсии в контексте совместимости присваивания.То есть, если у нас есть Func<Mammal, Mammal>
в руке, мы можем присвоить его переменной типа Func<Giraffe, Animal>
и знать, что основная функция всегда будет забирать млекопитающего - потому что теперь он будет получать только жирафов - и всегда будетвернуть животное - потому что оно возвращает млекопитающих.
Но мы также знаем, что делегаты могут быть добавлены вместе;делегаты являются неизменяемыми, поэтому при добавлении двух делегатов вместе получается третий;сумма представляет собой последовательную композицию слагаемых.
Полеподобные события реализуются с использованием суммирования делегатов;поэтому добавление обработчика к событию представляется как +=
.(Я не большой поклонник этого синтаксиса, но мы застряли с ним сейчас.)
Хотя обе эти функции работают хорошо независимо друг от друга, они плохо работают в комбинации.Когда я реализовал дисперсию делегатов, наши тесты в короткие сроки обнаружили, что в CLR было несколько ошибок, связанных с добавлением делегатов, когда базовые типы делегатов не соответствовали из-за преобразований с поддержкой дисперсии.Эти ошибки существовали со времен CLR 2.0, но до C # 4.0 ни один основной язык не обнаруживал ошибок, не было написано ни одного теста для них и т. Д.
К сожалению, я не помню, чторепродукторы для багов были;это было двенадцать лет назад, и я не знаю, есть ли на нем какие-нибудь заметки, спрятанные где-нибудь на диске.
В то время мы работали с командой CLR, чтобы попытаться устранить эти ошибки для следующеговерсии CLR, но они не считались достаточно приоритетными по сравнению с их риском.Многие типы, такие как IEnumerable<T>
и IComparable<T>
и т. Д. Были сделаны вариантами в этих выпусках, как и типы Func
и Action
, но редко складывают два несовпадающих Func
с использованиемвариант преобразования .Но для делегатов мероприятия их единственная цель в жизни - сложить вместе;они будут добавляться вместе все время, и если бы они были вариантами, был бы риск раскрытия этих ошибок большому количеству пользователей.
Вскоре после C # 4 я потерял учет проблем и, честно говоря, не знаю, были ли они когда-нибудь решены.Попробуйте сложить вместе несколько несовпадающих делегатов в различных комбинациях и посмотрите, не случится ли что-нибудь плохое!
Так что это хорошая, но неудачная причина, почему не делает вариант делегатов событий в период выпуска C # 4.0.Есть ли еще веская причина, я не знаю.Вы должны спросить кого-то из команды CLR.