I have a parser that builds a list of variables and a list of expressions.
I put those into a block expression and compile ...

var blk = Expression.Convert(Expression.Block(Parser.m_Vars, Parser.m_Expr),typeof(CVar));
            var expr = Expression.Lambda<Func<CVar>>(blk);
            var result = "";

            try
            {
               var actionX = expr.Compile();
               result = actionX();
            }

The resulting tree looks like this ...

.Lambda #Lambda1<System.Func`1[CVar]>() {
    (CVar).Block(
        CVar $Test1,
        CVar $Test2) {
        $Test1 = (CVar)"Foo ";
        $Test2 = (CVar)"Bar ";
        $Test1 + $Test2
    }
}

The compile method throws an exception "variable 'Test1' of type 'CVar' referenced from scope '', but it is not defined".

If I build an identical tree in code ...

var exprs = new List<Expression>();
            var vars = new List<ParameterExpression>();

            vars.Add(Expression.Parameter(typeof(CVar), "Test1"));
            vars.Add(Expression.Parameter(typeof(CVar), "Test2"));
            exprs.Add(Expression.Assign(vars[0], Expression.Convert(Expression.Constant("Foo "), typeof(CVar))));
            exprs.Add(Expression.Assign(vars[1], Expression.Convert(Expression.Constant("Bar "), typeof(CVar))));
            exprs.Add(Expression.Add(vars[0], vars[1]));

            var blk1 = Expression.Convert(Expression.Block(vars, exprs), typeof(CVar));
            var expr1 = Expression.Lambda<Func<CVar>>(blk1);
            var action1 = expr1.Compile();

            var result1 = action1();

It works like it's supposed to.

Both trees are identical as far as I can tell in the 2010 debug visualizer and in the old 2008 visualiser.

I'm at a loss.

Yes! I figured it out!

When the parser first encounters a variable it defines & assigns it

var p1 = Expression.Parameter(typeof(CVar), "Test1"));
   m_Vars,Add(p1);
   m_exprs.Add(Expression.Assign(p1, Expression.Convert(Expression.Constant("Foo "), typeof(CVar))));

Later when it's used a parameter expression is created for the reference ...

var p1 = Expression.Parameter(typeof(CVar), "Test1"));
   var p2 = Expression.Parameter(typeof(CVar), "Test2"));

   m_exprs.Add(Expression.Add(p1, p2));

This cannot be done! You MUST use the original ParameterExpression created above!

var p1 = GetVariable("Test1"));
   var p2 = GetVariable("Test2"));

   m_exprs.Add(Expression.Add(p1, p2));

I don't understand why it would be that way, it's just an expression. But I guess there is a reason. It would allow you to manage unnamed variables I suppose.

Anyways, Woot!

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.