Expressions breaking code when compiled using VS2015 Update 1

余生长醉 提交于 2020-01-01 03:58:07

问题


After installing Visual Studio 2015 Update 1 on my machine I saw that some of my unit tests failed. After doing some investigation I was able to reduce the problem to this line of code:

Expression<Func<GameObject, bool>> expression = t => t.X == 0 && t.Y == 0 && t.GameObjectType == GameObjectType.WindMill;

When hovering over the expression variable the results were different in the versions of Visual Studio:

VS 2015:

VS 2015 Update 1:

The logic that was doing the comparison for the enums (somewhere in ServiceStack.OrmLite code) now acted differently which then eventually resulted in the enum not being recognized as an enum, resulting in the failing unit test.

I was able to reproduce the problem using the following code:

class Program
{
    static void Main(string[] args)
    {
        var gameObjects = new List<GameObject> {
            new GameObject { X = 0, Y = 0, GameObjectType = GameObjectType.WindMill },
            new GameObject { X = 0, Y = 1, GameObjectType = GameObjectType.Pipe },
            new GameObject { X = 0, Y = 2, GameObjectType = GameObjectType.Factory }
        };

        var gameObjectsQueryable = gameObjects.AsQueryable();

        Expression<Func<GameObject, bool>> expression = t => t.X == 0 && t.Y == 0 && t.GameObjectType == GameObjectType.WindMill;

        var result = gameObjectsQueryable.Where(expression);

        var resultAsList = result.ToList();

        foreach (var item in resultAsList)
        {
            Console.WriteLine(item);
        }

        //Obtain the t.GameObjectType == GameObjectType.WindMill part
        var binaryExpression = expression.Body as BinaryExpression;
        var right = binaryExpression.Right;
        var binaryExpression2 = right as BinaryExpression;
        var right2 = binaryExpression2.Right;

        if (right2 is UnaryExpression)
        {
            Console.WriteLine("Found UnaryExpression (This happens when the solution is build with VS2015)...");

            var right2Unary = binaryExpression2.Right as UnaryExpression;
            var right2Constant = right2Unary.Operand as ConstantExpression;
            CheckIfConsantIsAsExpected(right2Constant);
        }
        else
        {
            Console.WriteLine("Found ConstantExpression (This happens when the solution is build with VS2015 Update 1)...");

            var right2Constant = binaryExpression2.Right as ConstantExpression;
            CheckIfConsantIsAsExpected(right2Constant);
        }

        Console.ReadKey();
    }

    public static void CheckIfConsantIsAsExpected(ConstantExpression expression)
    {
        if (expression.Value.Equals(GameObjectType.WindMill))
        {
            Console.WriteLine($"The value is the enum we expected :), : {expression.Value}");
        }
        else
        {
            Console.WriteLine($"The value is not the enum we expected :(, : {expression.Value}");
        }
    }
}

public class GameObject
{
    public int X { get; set; }
    public int Y { get; set; }
    public GameObjectType GameObjectType { get; set; }

    public override string ToString()
    {
        return $"{X},{Y}: {GameObjectType}";
    }
}

public enum GameObjectType
{
    WindMill = 100,
    Pipe = 200,
    Factory = 300
}

On VS 2015 it will go into the UnaryExpression path, and in VS 2015 Update 1 it will go into the ConstantExpression path.

If you compile the solution on VS 2015 and then copy the compiled .exe file to a VS 2015 Update 1 system it will run the same as the VS 2015 version (So also the UnaryExpression path). This suggests it is not JIT related but instead build related.

My question would be if this is intended? (Since it could break existing code when simply recompiling the solution)


回答1:


This appears to be something that was actually broken with the RTM VS2015. If you compile it without the old version of Roslyn it is actually a ConstantExpression.

4.5 compiler: https://dotnetfiddle.net/XpKg10
Roslyn compiler: https://dotnetfiddle.net/zeGVdh



来源:https://stackoverflow.com/questions/34099809/expressions-breaking-code-when-compiled-using-vs2015-update-1

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!