What does ExpressionVisitor.Visit<T> Do?
Asked Answered
T

1

8

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.

Transarctic answered 5/7, 2010 at 17:27 Comment(0)
P
5

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.

Pilcomayo answered 5/7, 2010 at 17:35 Comment(3)
I would have expected it to visit the entire tree in addLambdaExpression, not just addLambdaExpression itself.Transarctic
In that case you'll want to inherit a custom type from ExpressionVisitor and handle the NodeType.Lambda in the Visit() method.Pilcomayo
Any chance you know how to convert subtractExpression back to Expression<Func<int, int, int>>? I don't seem to find a complete example anywhere...Slant

© 2022 - 2024 — McMap. All rights reserved.