If I have function like this
double GetExpression(int x, int y, int z)
{
return x * y + z;
}
is it possible to modify it somehow, to not return result immediately only some object which is expression and then evaluate it this way:
var expression = GetExpression(1,2,3);
double result = expression.Execute() or expression.Evaluate()
other words just return function ?
Well, you could use delegates, and return a 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 that what you were looking for?
Now each time you call expression()
it will execute the code in the lambda expression. You can observe that if you use code which doesn't just return the same value each 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());
}
That will print 10 random numbers in the range [0, 10). Note that this will only create one instance of Random
(avoiding a common problem) - each time you call expression()
it will call the Next()
method on the same instance. The constructor for Random
is called in the "normal" part of the method - it's not in the lambda expression. So that gets executed when you first call the GetExpression
method (even if you never call expression()
afterwards).
Note however that the arguments to your GetExpression
were still passed by value though, and are captured by the lambda express. So consider this:
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 list
variable has been captured, so changes the the object that the value refers to are visible in the lambda expression, but changes to the x
variable itself are not visible in the lambda expression. (Likewise if you had list = new List<int>();
that change wouldn't be visible...
See more on this question at Stackoverflow