Ох, это совсем не просто. Func<T>
представляет собой общий delegate
, а не выражение. Если есть какой-либо способ сделать это (из-за оптимизаций и других действий, выполняемых компилятором, некоторые данные могут быть выброшены, поэтому может оказаться невозможным вернуть исходное выражение), это будет разборка IL на лету и вывод выражения (что ни в коем случае не легко). Обработка лямбда-выражений как данных (Expression<Func<T>>
) - это волшебство, совершаемое компилятором (в основном компилятор строит дерево выражений в коде, а не компилирует его в IL).
Связанный факт
Вот почему языки, которые толкают лямбды до крайности (например, Лисп), часто проще реализовать как интерпретаторы . В этих языках код и данные по сути одно и то же (даже в время выполнения ), но наш чип не может понять эту форму кода, поэтому мы должны эмулировать такую машину, создавая интерпретатор поверх тот, кто понимает это (выбор, сделанный Lisp-подобными языками) или жертвуя силой (код больше не будет точно равен данным) в некоторой степени (выбор, сделанный C #). В C # компилятор создает иллюзию обработки кода как данных, позволяя интерпретировать лямбды как code (Func<T>
) и data (Expression<Func<T>>
) при compile время .