Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create a static lambda for use with expression building?

Tags:

c#

lambda

c#-6.0

As of C# 6, lambdas now default to instance methods, and will never be static (which I assume means they always capture now, which I guess is more efficient [seems to be faster given the discussions]).

See here: Why has a lambda with no capture changed from a static in C# 5 to an instance method in C# 6?

and here: Difference in CSC and Roslyn compiler's static lambda expression evaluation?

This causes issues now with using lambdas when creating static MethodInfos for calls to expression methods such as Expression.Convert(Expression, typeof({SomeType}), conversionMethodInfo);

So then, what is the new way of doing this? I tried to use the "static" modifier with lambdas and it doesn't work. For those who can't imagine such code, this might be one example:

Func <T1,T2> converter = static v => ConvertT1ToT2(v); // ('T' is whatever type you want)
Expression.Convert(expression, typeof({SomeType}), converter.Method) // (error: converter.Method.IsStatic is false)

Yes, obviously it doesn't work.

like image 418
James Wilkins Avatar asked Apr 04 '17 21:04

James Wilkins


People also ask

Can we use lambda expression for static method?

A static method reference allows us to use a static method as a lambda expression. The static methods can be defined in a class, an interface, or an enum. The following code defines two lambda expressions.

Are lambda functions static?

A lambda or anonymous method may have a static modifier. The static modifier indicates that the lambda or anonymous method is a static anonymous function. A static anonymous function cannot capture state from the enclosing scope.

How do you use expression lambda?

To create a lambda expression, you specify input parameters (if any) on the left side of the lambda operator and an expression or a statement block on the other side. When you use method-based syntax to call the Enumerable. Select method in the System. Linq.

Can lambda expression be used without functional interface?

You do not have to create a functional interface in order to create lambda function.


2 Answers

So then, what is the new way of doing this?

There isn't one. The spec never promised anything about the implementation details of lambda expressions. Which is why you should not depend on them. It's also why What's new in C# 6 does not mention this.

Assuming you need to use Expression.Convert with a custom MethodInfo, then you should promote the lambda into a static method:

private static T2 Converter(T1 v)
{
    return ConvertT1ToT2(v);
}

…

MethodInfo converter =
    typeof(ThisType).GetMethod("Converter", BindingFlags.NonPublic | BindingFlags.Static);
// OR:
MethodInfo converter = ((Func<T1, T2>)Converter).Method;

Expression.Convert(expression, typeof(SomeType), converter)

This way, you're not using a lambda, so it's guaranteed the MethodInfo refers to a static method.

like image 152
svick Avatar answered Nov 13 '22 00:11

svick


In case others wish to know, in the end, I had to promote (demote? lol) my expressions to "Expression-bodied function members" instead, like this:

// (class method)
static string _Convert(object obj) => (obj as SomeType)?.SomeProperty ?? ReturnSomethingElse;

then in my method body:

Func<object, string> conversionDelegate = _Convert;
Expression exp = Expression.Convert(expression, typeof(SomeType), conversionDelegate.Method);

Edit: Some talk about non-capturing/static lambdas here: https://github.com/dotnet/csharplang/issues/275

like image 1
James Wilkins Avatar answered Nov 13 '22 00:11

James Wilkins