roslyn icon indicating copy to clipboard operation
roslyn copied to clipboard

Precompile compile-time declared Lambda Expression.

Open Liero opened this issue 1 year ago • 2 comments

Background and Motivation

Many UI Frameworks and libraries like Blazor, data grids, mappers, etc. required both

  1. LambdaExpression in order get reflection metadata such as PropertyInfo
  2. Func ekvivalent of the LambdaExpression (compiled lambda) in order to get actual value

For example:

<FormField Field="() => FirstName" />

or

mapper.Map(source => Source.FirstName, target => target.First_Name);

The library authors either go for runtime compilation (slow) or requires consumers to declare both, LambdaExpression and Func, although they look the same (DRY violation).

Proposed Change

A compiler should be able to optimize a compile time declared LambdaExpression so that the Compile() is fast. If lambda expression parameter types, return type and captured variables' types are known to the compiler, it should be possible to generate Func<>, shouldn't it?

There is actually no public API change needed.

A naive example

LambdaExpression<Func<string>> lambda = () => "Hello world!";

Roslyn will generate Func<string> equivalent and associate it with the lambda

Func<string> compiled_lambda = () => "Hello world!";
lambda.__compiled = compiled_lambda;

It's probably more difficult when there are captured variables, but some precompilation steps should be possible so that LambdaExpression.Compile() is fast.

Alternative Designs

A razor compiler actually generates both, LambdaExpression and Func for @bind directive. Consider more general approach, such as System.Runtime.CompilerServices attributes similar to [CallerMemberName]

void Foo<T>(LambdaExpression<Func<T>> expression, [CompileMember("expression")] Func<T> valueGetter = default!)
{
     string propertyName = FindPropertyName(expression);
     Console.WriteLine($"{propertyName}: {valueGetter()}");
}
var person = new Person { FirstName = "Daniel" }
foo(() => person.FirstName); //writes FirstName: Daniel

Liero avatar Jun 27 '24 07:06 Liero

Sounds like that could be an external source generator, perhaps combined with an interceptor (to intercept the Compile() call)

jjonescz avatar Jun 27 '24 08:06 jjonescz

A compiler should be able to optimize a compile time declared LambdaExpression so that the Compile() is fast.

The word should here though is rather vague. It's possible yes that it should be able to but what is the design that leads to us doing this?

jaredpar avatar Jun 27 '24 23:06 jaredpar

Closing due to lack of activity.

jaredpar avatar Oct 08 '24 16:10 jaredpar