Как уже отмечалось, проблема в том, что типы делегатов не являются "структурными".То есть они не имеют эквивалентности, основанной на их «структуре».
Теперь, возможно, это хорошо для некоторых типов.Если у вас есть
struct MyRectangle { int x; int y; int width; int height; ... }
и
struct YourRectangle { int x1; int y1; int x2; int y2; ... }
, очевидно, что было бы ошибкой разрешать присваивать экземпляры MyRectangle переменным YourRectangle, просто потому что они оба состояли из четырех целых.Семантика для целых отличается и, следовательно, типы не эквивалентны.
Теоретически, то же самое верно и для делегатов.Вы можете иметь
delegate int Pure(string x);
delegate int Func(string x);
, где «чистая» функция - это функция без побочных эффектов и один и тот же выход при одинаковом входе.Поскольку каждый Pure логически является Func, но каждый Func не обязательно является Pure, между ними не должно быть структурной типизации.
На практике, конечно, система типов не поддерживает такие понятия, как «чистая функция».Что ж.И на практике подавляющее большинство попыток преобразования между типами делегатов совершенно безопасны: преобразование из Func<int, bool>
в Predicate<int>
и так далее.
Итак, две вещи, одна смотрит назад, а другая смотрит вперед.В обратном направлении: если бы нам пришлось делать все это снова, я думаю, что делегаты, вероятно, были бы структурно набраны в CLI.Вы не всегда знаете, какие функции будут полезны при разработке совершенно новой структуры, и неструктурные типы делегатов до сих пор оказались не такими полезными, как, возможно, предполагалось.Вперед: я ожидаю увидеть больше функций в будущих версиях CLR, которые позволят более структурную типизацию.Например, функция «без pia» в C # 4 состоит в том, чтобы сделать два типа, которые семантически и структурно одинаковы, но определены в разных сборках, логически объединить структурно.