Подтвердить что ты не робот

Выражения, разбивающие код при компиляции с использованием VS2015 Update 1

После установки обновления Visual Studio 2015 Update 1 на моем компьютере я увидел, что некоторые из моих модульных тестов не удались. После некоторого исследования я смог уменьшить проблему до этой строки кода:

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

При зависании над переменной выражения результаты были разными в версиях Visual Studio:

VS 2015: VS 2015

VS 2015 Обновление 1: VS 2015 Update 1

Логика, которая выполняла сравнение для перечислений (где-то в коде ServiceStack.OrmLite), теперь действовала по-разному, что в итоге привело к тому, что перечисление не было признано как перечисление, в результате чего произошел сбой unit test.

Я смог воспроизвести проблему, используя следующий код:

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 Update 1 он перейдет в путь ConstantExpression.

Если вы скомпилируете решение на VS 2015 и затем скопируете скомпилированный .exe файл в систему VS 2015 Update 1, он будет работать так же, как версия VS 2015 (так же путь UnaryExpression). Это говорит о том, что он не связан с JIT, а создает взаимосвязь.

Мой вопрос будет, если это предназначено? (Так как он может сломать существующий код, просто перекомпилируя решение)

4b9b3361

Ответ 1

Это похоже на то, что было фактически нарушено с RTM VS2015. Если вы скомпилируете его без старой версии Roslyn, это на самом деле ConstantExpression.

4.5 компилятор: https://dotnetfiddle.net/XpKg10
Компилятор Roslyn: https://dotnetfiddle.net/zeGVdh