Language : C# .Net Version : 8.0 IDE : VS2020 / VSCode OS : Windows11
Is there no way for Csharp to write a truly static λ expression?
I studied currying today and wrote a function :
using System.Linq.Expressions;
using Curryfy;
object Apply(Delegate _operator, object? arg1)
{
Type t = _operator.GetType();
if (!t.IsGenericType || t.GenericTypeArguments.Length < 2 || t.Name != "Func`" + t.GenericTypeArguments.Length)
throw new Exception();
var args = _operator.Method.GetParameters().Select(p => Expression.Variable(p.ParameterType)).ToArray();
Expression expression = Expression.Call(_operator.Method, args);
foreach (var arg in args.Reverse())
expression = *Expression.Lambda(expression, arg);*
Console.WriteLine(expression);
return null;
}
***int sum(int a, int b) => a + b;***
System.Console.WriteLine(sum);
Apply(sum, 10);
It can run correctly and the results are as I expected :
System.Func`3[System.Int32,System.Int32,System.Int32]
Param_0 => Param_1 => <<Main>$>g__sum|0_1(Param_0, Param_1)
This sum function doesn't even use 'static'. But when I change this line to :
Func<int, int, int> sum = static (int a, int b) => a + b;
The Expression.Call(_operator.Method, args) throw a exception said :
Static method requires null instance, non-static method requires non-null instance.
What is the essential difference between these two ways of writing?
update at 14:34 1/11/2024:
Inspired by Michael Liu, I changed these implementation of sum to :
var a = Expression.Variable(typeof(int));
var b = Expression.Variable(typeof(int));
var aplusb = Expression.Add(a, b);
var sumExpression = Expression.Lambda(aplusb, a, b);
var sum = sumExpression.Compile();
Then Expression.Call(_operator.Method, args) didn't throw any exception.
You can use a
Func<T in, T out>to store the lambda expression statically.T inis the data type used for the input andT outis the data type for the output.You can invoke the result synchrounously using the
Invokemethod and pass the input to it.If you want to call it asynchronously, .NET Core is not supporting the
BeginInvokeandEndInvokecalls, so you will have to call theInvokemethod in aTask<T>method in order to call it asynchronously.