Skip to content

Commit

Permalink
Merge pull request #1746 from riganti/fix/ternary-operator-conversion
Browse files Browse the repository at this point in the history
Added a failing test for conditional operator nullable conversions
  • Loading branch information
tomasherceg authored Dec 1, 2023
2 parents 6ec1acf + 046206c commit 3817d9f
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,7 @@ protected override Expression VisitConditionalExpression(ConditionalExpressionBi
Debug.Assert(trueConverted.Type != falseConverted.Type);
// 1. We represent some "typeless expressions" as expression of type object
// 2. We allow conversion to string and also have the implicit conversion from string literal to enum
// 3. For some reason, we allow T? -> T implicit conversion as well as T -> T?, this will prefer the nullable type
// -> if we have an ambiguity, try to solve it by preferring the more specific type

if (trueConverted.Type == typeof(object))
Expand All @@ -335,6 +336,13 @@ protected override Expression VisitConditionalExpression(ConditionalExpressionBi
falseExpr = falseConverted;
else if (falseConverted.Type == typeof(string))
trueExpr = trueConverted;
else if (trueConverted.Type.UnwrapNullableType() == falseConverted.Type.UnwrapNullableType())
{
if (trueConverted.Type.IsNullable())
falseExpr = falseConverted;
else
trueExpr = trueConverted;
}
else
throw new BindingCompilationException($"Type of conditional expression '{node.ToDisplayString()}' cannot be determined because because '{trueExpr.Type.ToCode()}' and '{falseExpr.Type.ToCode()}' implicitly convert to one another", node);
}
Expand Down
23 changes: 23 additions & 0 deletions src/Tests/Binding/BindingCompilationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -835,6 +835,29 @@ public void BindingCompiler_ImplicitConversion_ConditionalStringAndNull()
Assert.IsNull(resultNull);
}

[TestMethod]
public void BindingCompiler_ImplicitConversion_ConditionalNullableAndNonNullable()
{
var resultNotNull = ExecuteBinding("_this.BoolProp ? _this.NullableDoubleProp : _this.DoubleProp", new[] { new TestViewModel { NullableDoubleProp = 11.1, DoubleProp = 22.2, BoolProp = true } }, expectedType: typeof(double?));
Assert.AreEqual(11.1, resultNotNull);
resultNotNull = ExecuteBinding("!_this.BoolProp ? _this.NullableDoubleProp : _this.DoubleProp", new[] { new TestViewModel { NullableDoubleProp = 11.1, DoubleProp = 22.2, BoolProp = true } }, expectedType: typeof(double?));
Assert.AreEqual(22.2, resultNotNull);
var resultNull = ExecuteBinding("_this.BoolProp ? null : _this.DoubleProp", new[] { new TestViewModel { NullableDoubleProp = 11.1, DoubleProp = 22.2, BoolProp = true } }, expectedType: typeof(object));
Assert.IsNull(resultNull);

}

[TestMethod]
public void BindingCompiler_ImplicitConversion_ConditionalNullableAndNonNullable_IntDouble()
{
var resultNotNull = ExecuteBinding("_this.BoolProp ? _this.NullableDoubleProp : _this.IntProp", new[] { new TestViewModel { NullableDoubleProp = 11.1, IntProp = 1, BoolProp = true } });
Assert.AreEqual(11.1, resultNotNull);
resultNotNull = ExecuteBinding("!_this.BoolProp ? _this.NullableDoubleProp : _this.IntProp", new[] { new TestViewModel { NullableDoubleProp = 11.1, IntProp = 1, BoolProp = true } }, expectedType: typeof(double?));
Assert.AreEqual(1.0, resultNotNull);
resultNotNull = ExecuteBinding("_this.BoolProp ? _this.NullableIntProp : _this.DoubleProp", new[] { new TestViewModel { DoubleProp = 11.1, NullableIntProp = 1, BoolProp = true } }, expectedType: typeof(double?));
Assert.AreEqual(1.0, resultNotNull);
}

[TestMethod]
public void BindingCompiler_ImplicitConversion_ConditionalEnumAndLiteral()
{
Expand Down

0 comments on commit 3817d9f

Please sign in to comment.