Remove unnecessary converts from expression trees. - by Paulo Zemek

Status : 

  Won't Fix<br /><br />
		Due to several factors the product team decided to focus its efforts on other items.<br /><br />
		A more detailed explanation for the resolution of this particular item may have been provided in the comments section.


1
0
Sign in
to vote
ID 549615 Comments
Status Closed Workarounds
Type Bug Repros 0
Opened 4/8/2010 6:35:52 AM
Access Restriction Public

Description

I don't know if, when compiling, converting two bytes to an int speed things up, but when generating expression trees, a comparison between 2 bytes must never generate two converts to int, to then do the comparison.
Sign in to post a comment.
Posted by Microsoft on 7/20/2010 at 6:02 PM
The best way to discover this for a particular expression is to see what the equivalent VB expression compiles to. Note that VB has its own particular semantics to maintain, and so similar expressions may yield somewhat different trees. When possible, common nodes are used that represent the logical operation performed (such as Add), with a custom MethodInfo if a particular language needs to inject its own semantics upon compilation. However, this custom MethodInfo cannot change the return type of the expression node. Convert nodes are therefore used to translate expressions to the expected type and should make up the vast majority of "extra" nodes that you must parse around within Expression Trees built by compilers.

Alex Turner
Program Manager
Visual Basic and C# Compiler
Posted by Paulo Zemek on 6/30/2010 at 12:39 PM
Does all other languages generate expression trees like C#?
Posted by Microsoft on 6/25/2010 at 7:32 AM
We'd be hesitant to add such knobs to our expression tree output now, as this would introduce an entirely new mode for expression trees that all expression tree consumers would need to support. Note also that a major benefit of expression trees is their composability - given two expression trees representing conditions, you can reliably stitch them together in an API to form a joint condition, regardless of what language compiler originally built the expression trees. The more distinct "modes" expression trees can find themselves in, the less feasible it is in the end to construct general APIs that operate over them.

Alex Turner
Program Manager
Visual Basic and C# Compiler
Posted by Paulo Zemek on 5/10/2010 at 8:01 AM
For example, updating my old code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;

namespace ExpressionTreeErrors
{
    public enum MyEnum
    {
        MyItem1,
        MyItem2
    }
    class Program
    {
        static void Main(string[] args)
        {
            avoidconverts
            {
                byte a = 1;
                byte b = 2;
                ShowExpression(() => a == b);
            
            
                MyEnum value1 = MyEnum.MyItem1;
                MyEnum value2 = MyEnum.MyItem2;
                ShowExpression(() => value1!=value2);
            }
            
            Console.ReadLine();
        }
        public static void ShowExpression(Expression<Func<bool>> expression)
        {
            Console.WriteLine(expression);
        }
    }
}


So, the keywords could be "avoidconverts" and "allowconverts".
Posted by Paulo Zemek on 5/10/2010 at 7:54 AM
Isn't possible to add a compiler option for this? Or a keyword before/after the expression tree to avoid such conversions?
Posted by Microsoft on 5/10/2010 at 5:14 AM
Thanks for reporting this issue you've encountered with Visual Studio 2008!

The way C# encodes expressions as expression trees is a balancing act between keeping the resulting tree simple and accurately encoding C#'s actual expression semantics. Throughout C# expression compilation, we've decided to lean mostly on the side of maintaining C#'s exact semantics, so that compiling this expression tree is most likely to produce the same hehavior as compiling the equivalent code in a standard statement.

In this case, the C# specification states that there are no built-in conversions defined for < between byte values - instead the values must be promoted by the compiler to int so that those values may be compared. The expression tree emitted by the C# Compiler is following these semantics. As this is now the expected shape of expression trees, it's too late to change such a fundamental design principle of the trees we emit. APIs consuming expression trees must properly process conversion nodes to determine and use the expression's "true" return type.

Alex Turner
Program Manager
Visual C# Compiler
Posted by Microsoft on 4/14/2010 at 3:44 PM
Ok, I understand what your scenario is now (it's not about expression tree behavior, but how C# generates expression trees in this case). I'll pass along this feedback to the compiler team.
Posted by Paulo Zemek on 4/12/2010 at 7:54 PM
I atached a sample project.
I am targetting .Net 3.5.

A sample code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;

namespace ExpressionTreeErrors
{
    public enum MyEnum
    {
        MyItem1,
        MyItem2
    }
    class Program
    {
        static void Main(string[] args)
        {
            byte a = 1;
            byte b = 2;
            ShowExpression(() => a == b);
            
            
            MyEnum value1 = MyEnum.MyItem1;
            MyEnum value2 = MyEnum.MyItem2;
            ShowExpression(() => value1!=value2);
            
            Console.ReadLine();
        }
        public static void ShowExpression(Expression<Func<bool>> expression)
        {
            Console.WriteLine(expression);
        }
    }
}


And the result is:

() => (Convert(value(ExpressionTreeErrors.Program+<>c__DisplayClass0).a) = Convert(value(ExpressionTreeErrors.Program+<>c__DisplayClass0).b))
() => (Convert(value(ExpressionTreeErrors.Program+<>c__DisplayClass0).value1) != Convert(value(ExpressionTreeErrors.Program+<>c__DisplayClass0).value2))


So, there are converts in both sides of the expression, even when both sides are of the same type.
Posted by Microsoft on 4/12/2010 at 4:49 PM
Thanks for the feedback! Unfortunately, we don't see don't see this behavior. Can you please

1) Paste in a small snippit of code that reproduces the problem.
2) What version of the framework are you targeting in your app?

thanks in advance!

Toddap@MS
Posted by Microsoft on 4/8/2010 at 9:55 PM
Thanks for your feedback.

We are rerouting this issue to the appropriate group within the Visual Studio Product Team for triage and resolution. These specialized experts will follow-up with your issue.

Thank you