Returned expression instead of result

If I have a function like this

double GetExpression(int x, int y, int z)
{
    return x * y + z;
}

      

Is there any way I can modify it so that it doesn't immediately return the result to just some object that is an expression, and then evaluates it like this:

var expression = GetExpression(1,2,3);
double result = expression.Execute() or expression.Evaluate()

      

other words just return function

+3


source to share


3 answers


Yes!

Func<double> GetExpression(int x, int y, int z)
{
    return () => x * y + z;
}

      



use like:

var expression = GetExpression(1,2,3);
double result = expression();

      

+7


source


Well, you can use delegates and return Func<double>

:

Func<double> GetExpression(int x, int y, int z)
{
    return () => x * y + z;
}

var expression = GetExpression(1,2,3);
double result = expression(); // Or expression.Invoke()

      

Is this what you were looking for?

Now every time you call expression()

it executes the code in the lambda expression . You may notice that if you are using code that not only returns the same value every time. For example:

Func<int> GetExpression()
{
    Random rng = new Random();
    return () => rng.Next(10);
}

var expression = GetExpression();
for (int i = 0; i < 10; i++)
{
     Console.WriteLine(expression());
}

      



This will print 10 random numbers in the range [0, 10]. Note that this will only create one instance Random

(avoiding the common problem ) - every time you call expression()

, it calls Next()

on the same instance. The constructor for Random

is called in the "normal" part of the method - it is not in the lambda expression. This way, execution is done when you call the method first GetExpression

(even if you never call expression()

afterwards).

Note, however, that your arguments were GetExpression

still passed by value and were captured by the lambda express. Therefore, consider the following:

Func<int> GetExpression(int a, List<int> b)
{
    return () => a + b.Count;
}

int x = 10;
List<int> list = new List<int> { 1, 2, 3 };
var expression = GetExpression(x, list);
Console.WriteLine(expression()); // 13
x = 20;
list.Add(100);
Console.WriteLine(expression()); // 14

      

Here the value of the variable has list

been written, so changes to the object to which the value belongs are visible in the lambda expression, but changes to the variable itself are x

not reflected in the lambda expression. (Likewise, if you had list = new List<int>();

, the change would not be visible ...

+7


source


To expand on Jon Skeet's answer about capturing variables, if you don't want to, you can do something like this:

double GetExpression(int x, int y, int z)
{
    return x * y + z;
}

Func<int, int, int, double> expression = GetExpression;

for (int i = 0; i < 10; i++)
    Console.WriteLine("{0}", expression(i, i+1, i+2));

      

This avoids modifying existing code (in case you want to point to a function you didn't have) and avoids capturing values ​​outside of lamda.

+2


source







All Articles