Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does ExpressionVisitor.Visit<T> Do?

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.

like image 282
Jeff Avatar asked Jul 05 '10 17:07

Jeff


1 Answers

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.

like image 196
codekaizen Avatar answered Oct 03 '22 19:10

codekaizen