Здравствуйте, vdimas, Вы писали:
V>Таки, если в where используется простейшая лямбда-предикат, то её стоит инлайнить.
Так-то я не против. Я вообще бы хотел, чтобы JIT умел инлайнить известные делегаты. Но пока что все обсуждения подобной функциональности в соответствующих группах заканчиваются на том, что это hell lot of a job.
Была также мысль напилить хелперную библиотеку, которая бы умела делать constant propagation для всего, включая делегаты.
Ну, то есть берём метод типа add, и скармливаем его в Specialize:
Func<int, int, int> add = (a, b)=>a+b;
Func<int, int> add2 = Specialize(add, 2);
При этом этот add2 — это вовсе не вызов того же add с b=2, а по честному проинлайненный код делегата, соответствующий a=>a+2.
Для Expression это, понятное дало, тривиальное упражнение. А интересно, конечно, делать это для готовых делегатов.
И точно также для
Where(IEnumerable<int> e, Predicate<int> p) делаем
Specialize(Where, a => a%2==0), и получаем на выходе
Func<IEnumerable<int>, IEnumerable<int>>, внутри которой уже нет никаких вызовов делегатов, а только итерирование по аргументу и вызовы a%2==0.
А уже потом поверх такой библиотеки можно делать различные прикольные плюшки типа "а давайте оптимизируем нашу цепочку цепочек делегатов".
Но это всё тоже требует больших затрат; в проекте linq2d мне оно не пригодилось, а пока что больше применить мне некуда — поэтому идея лежит на полке.
V>Спасибо.
V>И почему до сих пор нет в дотнете, если разница такая впечатляющая?
Я не вдавался. Так-то есть и всякие интересные реализации расширений к самим Expression, которые пока что в дотнет не вошли.
Например, хорошо известная штука — в Expressions до сих пор нет поддержки Tuple Initializer или как он там называется.
То есть нельзя сделать
Expression<Func<int, (int, int)>> t = a=>(a, a);
Можно только
Expression<Func<int, (int, int)>> t = a=>Tuple.Create(a, a);
Хотя казалось бы — чего такого-то?