гипотезы Томаса довольно хороши. Его рассуждения о методах расширения являются точными. В основном, чтобы методы расширения работали, нам нужен сайт вызова, чтобы во время выполнения каким-то образом знать, какие директивы с использованием действовали во время компиляции . У нас просто не было достаточно времени или средств для разработки системы, с помощью которой эта информация могла бы сохраняться на сайте вызовов.
Для лямбда-ситуаций ситуация на самом деле более сложная, чем простая задача определения, собирается ли лямбда-выражение в дерево выражений или делегат. Учтите следующее:
d.M(123)
где d - выражение динамического типа. * Какой объект должен быть передан во время выполнения в качестве аргумента для вызова сайта "М"? Ясно, мы вставляем 123 и передаем это. Затем алгоритм разрешения перегрузки в связывателе времени выполнения просматривает тип времени выполнения d и тип времени компиляции int 123 и работает с этим.
А что если это было
d.M(x=>x.Foo())
Теперь, какой объект мы должны передать в качестве аргумента? У нас нет способа представить «лямбда-метод одной переменной, который вызывает неизвестную функцию с именем Foo для любого типа x».
Предположим, мы хотели реализовать эту функцию: что мы должны реализовать? Во-первых, нам нужен способ для представления несвязанной лямбды . Деревья выражений предназначены только для представления лямбд, где известны все типы и методы . Нам нужно изобрести новый вид «нетипизированного» дерева выражений. И тогда нам нужно будет внедрить все правил лямбда-связывания в связывателе времени выполнения.
Рассмотрим последний пункт. Лямбды могут содержать операторы . Для реализации этой функции требуется, чтобы связыватель времени выполнения содержал весь семантический анализатор для каждого возможного оператора в C # .
Это были порядки величины из нашего бюджета. Мы бы все еще работали над C # 4 сегодня, если бы хотели реализовать эту функцию.
К сожалению, это означает, что LINQ не очень хорошо работает с динамическими, потому что LINQ, конечно, везде использует нетипизированные лямбды. Надеемся, что в какой-то гипотетической будущей версии C # у нас будет более полнофункциональный механизм связывания во время выполнения и возможность делать гомоиконические представления несвязанных лямбд. Но я бы не задержал дыхание в ожидании на твоем месте.
ОБНОВЛЕНИЕ: комментарий требует разъяснения по поводу семантического анализатора.
Рассмотрим следующие перегрузки:
class C {
public void M(Func<IDisposable, int> f) { ... }
public void M(Func<int, int> f) { ... }
...
}
и звонок
d.M(x=> { using(x) { return 123; } });
Предположим, что d относится к динамическому типу времени компиляции и типу среды выполнения C. Что должен делать компоновщик времени выполнения?
Средство связывания во время выполнения должно определить во время выполнения , может ли выражение x=>{...}
преобразовываться в каждый из типов делегатов в каждой из перегрузок M.
Чтобы сделать это, связыватель времени выполнения должен быть в состоянии определить, что вторая перегрузка неприменима. Если бы это было применимо, то вы могли бы использовать int в качестве аргумента для оператора using, но аргумент для оператора using должен быть одноразовым. Это означает, что средство связывания времени выполнения должно знать все правила для оператора using и иметь возможность правильно сообщать, является ли любое возможное использование оператора using допустимым или недопустимым .
Очевидно, что это не ограничивается оператором использования. Связыватель времени выполнения должен знать все правила для всего C # , чтобы определить, можно ли преобразовать лямбда-оператор в данный тип делегата.
У нас не было времени написать механизм выполнения, который по сути был полностью новым компилятором C #, который генерирует деревья DLR, а не IL . Запретив лямбды, нам нужно только написать связыватель времени выполнения, который знает, как связывать вызовы методов, арифметические выражения и несколько других простых видов сайтов вызовов. Разрешение лямбды делает проблему связывания во время выполнения порядка десятков или сотен раз дороже в реализации, тестировании и обслуживании.