What does ExpressionVisitor.Visit<T> Do?

c#-4.0 expression-trees expressionvisitor linq

Question

Before someone shouts out the answer, please read the question through.

What is the purpose of the method in .NET 4.0's ExpressionVisitor:

public static ReadOnlyCollection<T> Visit<T>(ReadOnlyCollection<T> nodes, Func<T, T> elementVisitor)

My first guess as to the purpose of this method was that it would visit each node in each tree specified by the nodes parameter and rewrite the tree using the result of the elementVisitor function.

This does not appear to be the case. Actually this method appears to do a little more than nothing, unless I'm missing something here, which I strongly suspect I am...

I tried to use this method in my code and when things didn't work out as expected, I reflectored the method and found:

public static ReadOnlyCollection<T> Visit<T>(ReadOnlyCollection<T> nodes, Func<T, T> elementVisitor)
{
    T[] list = null;
    int index = 0;
    int count = nodes.Count;
    while (index < count)
    {
        T objA = elementVisitor(nodes[index]);
        if (list != null)
        {
            list[index] = objA;
        }
        else if (!object.ReferenceEquals(objA, nodes[index]))
        {
            list = new T[count];
            for (int i = 0; i < index; i++)
            {
                list[i] = nodes[i];
            }
            list[index] = objA;
        }
        index++;
    }
    if (list == null)
    {
        return nodes;
    }
    return new TrueReadOnlyCollection<T>(list);
}

So where would someone actually go about using this method? What am I missing here?

Thanks.

Accepted Answer

It looks to me like a convenience method to apply an aribitrary transform function to an expression tree, and return the resulting transformed tree, or the original tree if there is no change.

I can't see how this is any different of a pattern that a standard expression visitor, other than except for using a visitor type, it uses a function.

As for usage:

Expression<Func<int, int, int>> addLambdaExpression= (a, b) => a + b;

// Change add to subtract
Func<Expression, Expression> changeToSubtract = e => 
{ 
    if (e is BinaryExpression) 
    { 
        return Expression.Subtract((e as BinaryExpression).Left,
                                   (e as BinaryExpression).Right); 
    }
    else
    {
        return e;
    }
};  

var nodes = new Expression[] { addLambdaExpression.Body }.ToList().AsReadOnly();
var subtractExpression = ExpressionVisitor.Visit(nodes, changeToSubtract);

You don't explain how you expected it to behave and why therefore you think it does little more than nothing.




Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Is this KB legal? Yes, learn why
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Is this KB legal? Yes, learn why