Delegate evaluate order

I was trying to bind following operation on delegates: 2*2+2 this should give of course 6 but my example give 8

I thought that all delegates used here will not be evaluated until this linie

  var result = response();

but it works somehow other way then I was expected, I thought that under response variable delegate will be : EvaluateConst()() * EvaluateConst()() + EvaluateConst()() and this way math operators shold take priority from language specification but not.

        static void Main(string[] args)
        {
            var response = Mul();
            var result = response();
        }

        public static Func<double> Add()
        {
            return () => EvaluateConst()() + EvaluateConst()();
        }

        public static Func<double> Mul()
        {
            return () => EvaluateConst()() * Add()();
        }

        public static Func<double> EvaluateConst()
        {
            return () => 2;
        }

Is there a way by modifying this to achieve what I want ?

Intresting is that if set breakPoint on line return () => 2; debuger catch it only after finall evaluating in var result = response();

Jon Skeet
people
quotationmark

You're not evaluating 2 * 2 + 2. You're evaluating

2 * (2 + 2)

The fact that delegates are involved is irrelevant here - you're always evaluating them as soon as they're returned anyway. You can effectively rewrite the code as:

static void Main(string[] args)
{
    var result = Mul();
}

public static double Add()
{
    return EvaluateConst() + EvaluateConst();
}

public static double Mul()
{
    return EvaluateConst() * Add();
}

public static double EvaluateConst()
{
    return 2;
}

First understand why that returns 8, then you can go back to your delegate version. This is the line that does the multiplication:

return () => EvaluateConst()() * Add()();

When you call EvaluateConst, that returns a delegate that, when invoked, will return 2.

When you call Add, that returns a delegate that, when invoked, will return 4 (by way of itself calling EvaluateConst and invoking the delegate, doing that twice, and adding the results together).

So your lambda expression is converted into a delegate which, when invoked, basically evaluates 2 * 4.

If you want to evaluate 2 * 2 + 2, you should think of it as this:

     +
  *     2
2   2

In other words:

static void Main(string[] args)
{
    var response = Add();
    var result = response();
}

public static Func<double> Add()
{
    return () => Mul()() + EvaluateConst()();
}

public static Func<double> Mul()
{
    return () => EvaluateConst()() * EvaluateConst()();
}

... but again, the delegate side of this is really a red herring.

people

See more on this question at Stackoverflow