使用VS2015更新1编译表达式时断码 [英] Expressions breaking code when compiled using VS2015 Update 1

查看:304
本文介绍了使用VS2015更新1编译表达式时断码的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的机器上安装Visual Studio 2015更新1后,我看到了我的一些单元测试失败。做一些调查后,我能够把问题缩小到这行代码:

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;

当鼠标悬停在表达变量的结果是在Visual Studio的版本不同:

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

2015年VS:

2015年VS更新1:

VS 2015 Update 1:

这是做了枚举(在ServiceStack.OrmLite码的地方)的比较,现在不同的做法,然后最终导致枚举的逻辑都不会被识别为。枚举,导致失败的单元测试

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
}

在VS 2015年将进入UnaryExpression路径,并在VS 2015更新1将进入常量表达式路径。

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

如果您在编译VS 2015解决方案,然后编译后的.exe文件复制到VS 2015 Update 1的系统它将运行一样VS 2015年版(因此也是UnaryExpression路径)。这表明它不是JIT相关,而是建立相关

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)

推荐答案

这似乎是东西,实际上是与RTM破VS2015。如果你编译它没有老版本的罗斯林它实际上一个常量表达式是。

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编译器: https://dotnetfiddle.net/XpKg10结果
罗斯林编译:
https://dotnetfiddle.net/zeGVdh

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

这篇关于使用VS2015更新1编译表达式时断码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆