Expressions, die beim Kompilieren mit VS2015 Update 1 den Code brechen
Nach der Installation von Visual Studio 2015 Update 1 auf meinem Computer habe ich festgestellt, dass einige meiner Komponententests fehlgeschlagen sind. Nach einigen Nachforschungen konnte ich das Problem auf diese Codezeile reduzieren:
Expression<Func<GameObject, bool>> expression = t => t.X == 0 && t.Y == 0 && t.GameObjectType == GameObjectType.WindMill;
Wenn Sie mit der Maus über die Ausdrucksvariable fahren, unterscheiden sich die Ergebnisse in den Versionen von Visual Studio:
Die Logik, die den Vergleich für die Aufzählungen durchführte (irgendwo in ServiceStack.OrmLite-Code), verhielt sich jetzt anders, was schließlich dazu führte, dass die Aufzählung nicht als Aufzählung erkannt wurde und der Unit-Test fehlschlug.
Ich konnte das Problem mit dem folgenden Code reproduzieren:
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
}
Auf VS 2015 wird es in den UnaryExpression-Pfad und auf VS 2015 Update 1 in den ConstantExpression-Pfad verschoben.
Wenn Sie die Lösung in VS 2015 kompilieren und dann die kompilierte EXE-Datei auf ein VS 2015 Update 1-System kopieren, wird sie genauso ausgeführt wie die VS 2015-Version (also auch der UnaryExpression-Pfad). Dies deutet darauf hin, dass es sich nicht um eine JIT-bezogene, sondern um eine Build-bezogene handelt.
Meine Frage wäre, ob dies beabsichtigt ist? (Da es beim Neukompilieren der Lösung zu Problemen mit vorhandenem Code kommen kann)