Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/315.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用VS2015 Update 1编译时,表达式会中断代码_C#_.net_Visual Studio 2015_Expression Trees_.net 4.6 - Fatal编程技术网

C# 使用VS2015 Update 1编译时,表达式会中断代码

C# 使用VS2015 Update 1编译时,表达式会中断代码,c#,.net,visual-studio-2015,expression-trees,.net-4.6,C#,.net,Visual Studio 2015,Expression Trees,.net 4.6,在我的机器上安装Visual Studio 2015 Update 1后,我发现我的一些单元测试失败了。在做了一些调查之后,我能够将问题归结为以下代码行: Expression<Func<GameObject, bool>> expression = t => t.X == 0 && t.Y == 0 && t.GameObjectType == GameObjectType.WindMill; Expression=t=>t.X=

在我的机器上安装Visual Studio 2015 Update 1后,我发现我的一些单元测试失败了。在做了一些调查之后,我能够将问题归结为以下代码行:

Expression<Func<GameObject, bool>> expression = t => t.X == 0 && t.Y == 0 && t.GameObjectType == GameObjectType.WindMill;
Expression=t=>t.X==0&&t.Y==0&&t.GameObjectType==GameObjectType.WindMill;
将鼠标悬停在表达式变量上时,Visual Studio版本中的结果不同:

与2015年相比:

VS 2015更新1:

为枚举(ServiceStack.OrmLite代码中的某个地方)执行比较的逻辑现在的行为有所不同,这最终导致无法将枚举识别为枚举,从而导致单元测试失败

我能够使用以下代码重现问题:

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
}
类程序
{
静态void Main(字符串[]参数)
{
var gameObjects=新列表{
新游戏对象{X=0,Y=0,GameObjectType=GameObjectType.WindMill},
新游戏对象{X=0,Y=1,GameObjectType=GameObjectType.Pipe},
新游戏对象{X=0,Y=2,GameObjectType=GameObjectType.Factory}
};
var gameObjectsQueryable=gameObjects.AsQueryable();
Expression=t=>t.X==0&&t.Y==0&&t.GameObjectType==GameObjectType.WindMill;
var result=gameObjectsQueryable.Where(表达式);
var resultAsList=result.ToList();
foreach(结果列表中的变量项)
{
控制台写入线(项目);
}
//获取t.GameObjectType==GameObjectType.WindMill零件
var binaryExpression=expression.Body作为binaryExpression;
var right=binaryExpression.right;
var binaryExpression2=作为BinaryExpression的右边;
var right2=二进制表达式2.Right;
if(right2是一元表达式)
{
WriteLine(“找到了一个表达式(当使用VS2015构建解决方案时会发生这种情况)…”;
var right2Unary=binaryExpression2.Right作为一元表达式;
var right2Constant=right2一元。操作数为常量表达式;
检查预期的消费(右2常量);
}
其他的
{
Console.WriteLine(“发现ConstantPression(在使用VS2015更新1构建解决方案时发生此情况)…”;
var right2Constant=二进制表达式2.右为常量表达式;
检查预期的消费(右2常量);
}
Console.ReadKey();
}
公共静态无效检查ConsantisAsExpected(ConstantExpression表达式)
{
if(expression.Value.Equals(GameObjectType.WindMill))
{
WriteLine($“该值是我们期望的枚举:),:{expression.value}”);
}
其他的
{
WriteLine($”值不是我们期望的枚举:(,:{expression.value}”);
}
}
}
公共类游戏对象
{
公共整数X{get;set;}
公共整数Y{get;set;}
公共GameObjectType GameObjectType{get;set;}
公共重写字符串ToString()
{
返回$“{X},{Y}:{GameObjectType}”;
}
}
公共枚举GameObjectType
{
风车=100,
管道=200,
工厂=300
}
在VS 2015上,它将进入UnaryExpression路径,在VS 2015 Update 1中,它将进入ConstantExpression路径

如果您在VS 2015上编译解决方案,然后将编译后的.exe文件复制到VS 2015 Update 1系统,它将运行与VS 2015版本相同的版本(以及UnaryExpression路径)。这表明它与JIT无关,而是与生成相关


我的问题是,这是否是有意的?(因为在简单地重新编译解决方案时,它可能会破坏现有代码)

这似乎是RTM VS2015实际破坏的东西。如果在没有旧版本Roslyn的情况下编译它,它实际上是一个
ConstantExpression

4.5编译器:

Roslyn编译器:

对我来说,这看起来像是一个非常无辜的优化。我不希望它会破坏任何东西到无法工作的地步,但是:当然,它会在代码中采用不同的路径,因此检查采用哪条路径的测试将中断。但是,计算此表达式的最终结果应该保持不变,并且最终结果将是错误的将其转换为其他内容的结果应该会产生一些等效的结果。正在中断的代码将枚举序列化为SQL查询。现在这会中断,因为它不知道正在处理的值实际上是枚举。可能您有一个不同的程序集,其中包含引用到表达式中的常量?以及你只是没有正确地重建它…只是一个想法。你确定你的枚举位于同一个程序集中吗?我有几乎相同的问题。这里,问题发生在VS 2010和VS 2015中,但在LinqPad中没有问题。这是Roslyn引发的灾难。数千个错误,他们一直在破坏它们,因此版本在更新1中与RTM中的完全不同,很可能有自己的缺陷包。只需将自己的错误报告添加到堆中,单击按钮。