Expression trees - unnecessary conversion to int32

后端 未结 2 1118
一个人的身影
一个人的身影 2021-02-19 10:41

Expression trees seem to build an unnecessary conversion when working with bytes and shorts, they convert both sides (in binary expressions for instance) to int32.

This

2条回答
  •  清酒与你
    2021-02-19 10:49

    That's really interesting; unfortunately, the rules of the expression-tree compiler are not formally specified - there is a brief "are elsewhere" in the specification, but : they aren't really.

    If it is causing a problem, you could try to spot and remove it - something like below, which is 100% untested and use-at-own-risk, etc:

    static void Main()
    {
        Console.WriteLine(((Expression>)((s, s1) => s == s1)).Unmunge());
        Console.WriteLine(((Expression>)((s, s1) => s == s1)).Unmunge());  
    }
    static Expression Unmunge(this Expression expression)
    {
        return (Expression)RedundantConversionVisitor.Default.Visit(expression);
    }
    class RedundantConversionVisitor : ExpressionVisitor
    {
        private RedundantConversionVisitor() { }
        public static readonly RedundantConversionVisitor Default = new RedundantConversionVisitor();
        protected override Expression VisitBinary(BinaryExpression node)
        {
            if(node.Type == typeof(bool) && node.Method == null
                && node.Left.NodeType == ExpressionType.Convert && node.Right.NodeType == ExpressionType.Convert
                && node.Left.Type == node.Right.Type)
            {
                UnaryExpression lhs = (UnaryExpression)node.Left, rhs = (UnaryExpression)node.Right;
                if (lhs.Method == null && rhs.Method == null && lhs.Operand.Type == rhs.Operand.Type)
                {
                    // work directly on the inner values
                    return Expression.MakeBinary(node.NodeType, lhs.Operand, rhs.Operand, node.IsLiftedToNull, node.Method);
                }
            }
            return base.VisitBinary(node);
        }
    }
    

    Output before:

    (s, s1) => (Convert(s) == Convert(s1))
    (s, s1) => (Convert(s) == Convert(s1))
    

    Output after:

    (s, s1) => (s == s1)
    (s, s1) => (s == s1)
    

提交回复
热议问题