2015-12-05 5 views
21

Visual Studio 2015 Update 1をマシンにインストールした後、私のユニットテストの一部が失敗しました。いくつかの調査を行った後、私はこのコード行に問題を軽減することができました:VS2015アップデート1を使用してコンパイルしたときの式ブレークコード

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

結果は、Visual Studioのバージョンで異なっていた表現変数の上にマウスを移動:2015

VS: VS 2015

VS 2015の更新1:ServiceStack.Oのどこかに(列挙型のための比較をしていた VS 2015 Update 1

ロジックrmLiteコード)が異なる動作をしてしまい、最終的にenumがenumとして認識されず、失敗した単体テストが発生しました。 VS 2015では、それはUnaryExpressionパスになります

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 Update 1の中でそれがConstantExpressionパスになります。

は、私は次のコードを使用して問題を再現することができました。

VS 2015でソリューションをコンパイルし、コンパイルした.exeファイルをVS 2015 Update 1システムにコピーすると、VS 2015バージョンと同様に動作します(UnaryExpressionパスも同様)。これは、JITに関連するものではなく、関連するものであることを示しています。

これは私の質問ですか? (ソリューションを単に再コンパイルすると既存のコードが破損する可能性があるため)

+2

これはかなり私に罪のない最適化のように見えます。しかし、私はそれが動作していないという点で何かを壊すことは期待しません。確かに、それはコードを通る別の経路を取るでしょう。しかし、この式を評価する最終結果は同じままでなければならず、それを他のものに変換する最終的な結果は同等のものを生成するはずです。 – dasblinkenlight

+1

壊れていたコードは、列挙型をSQLクエリにシリアル化しました。これは、処理されている値が実際に列挙型であることを知らないため、これが壊れます。 – Devedse

+0

あなたの式に参照されている定数を含む別のアセンブリがあるかもしれませんか?そして、あなたはちょうどそれを正しく再構築しなかった...ちょっと考えた。列挙型が同じアセンブリ内にあることは確かですか? –

答えて

2

これは実際にはRTM VS2015で壊れているようです。あなたがRoslynの古いバージョンなしでそれをコンパイルすると、それは実際にはConstantExpressionです。

4.5コンパイラ:https://dotnetfiddle.net/XpKg10
ロザリンコンパイラ:https://dotnetfiddle.net/zeGVdh

関連する問題