C#: An item with the same key has already been added, when compiling expression

后端 未结 2 1722
攒了一身酷
攒了一身酷 2021-02-12 15:08

Ok, here\'s a tricky one. Hopefully there is an expression guru here who can spot what I am doing wrong here, cause I am just not getting it.

I am building up expression

2条回答
  •  清酒与你
    2021-02-12 15:55

    This is not an answer, but I hope it will help someone find the answer. I've simplified the code further so that it is just one single file and still fails in the same way. I have renamed the variables so that "x" is not used twice. I have removed the Range class and replaced it with hardcoded constants 0 and 1.

    using System;
    using System.Linq;
    using System.Linq.Expressions;
    
    class Program
    {
        static Expression> And(Expression> first,
                                               Expression> second)
        {
            var x = Expression.Parameter(typeof(int), "x");
            var body = Expression.AndAlso(Expression.Invoke(first, x), Expression.Invoke(second, x));
            return Expression.Lambda>(body, x);
        }
    
        static Expression> GetPredicateFor(Expression> selector)
        {
            var param = Expression.Parameter(typeof(int), "y");
            var member = Expression.Invoke(selector, param);
    
            Expression body =
                Expression.AndAlso(
                    Expression.GreaterThanOrEqual(member, Expression.Constant(0, typeof(int))),
                    Expression.LessThanOrEqual(member, Expression.Constant(1, typeof(int))));
    
            return Expression.Lambda>(body, param);
        }
    
        static void Main()
        {
            Expression> predicate = a => true;
            predicate = And(predicate, GetPredicateFor(b => b)); // Comment out this line and it will run without error
            var z = predicate.Compile();
        }
    }
    

    The expression looks like this in the debugger:

    x => (Invoke(a => True,x) && Invoke(y => ((Invoke(b => b,y) >= 0) && (Invoke(b => b,y) <= 1)),x))
    

    Update: I've simplified it down to about the most simple it can be while still throwing the same exception:

    using System;
    using System.Linq;
    using System.Linq.Expressions;
    
    class Program
    {
        static void Main()
        {
            Expression> selector = b => true;
            ParameterExpression param = Expression.Parameter(typeof(int), "y");
            InvocationExpression member = Expression.Invoke(selector, param);
            Expression body = Expression.AndAlso(member, member);
            Expression> predicate = Expression.Lambda>(body, param);
            var z = predicate.Compile();
        }
    }
    

提交回复
热议问题