diff --git a/Source/CSharp/Expressive/Expressive.Tests/Expressions/Binary/Logical/AndExpressionTests.cs b/Source/CSharp/Expressive/Expressive.Tests/Expressions/Binary/Logical/AndExpressionTests.cs index 1c9ab67..c7eb9d0 100644 --- a/Source/CSharp/Expressive/Expressive.Tests/Expressions/Binary/Logical/AndExpressionTests.cs +++ b/Source/CSharp/Expressive/Expressive.Tests/Expressions/Binary/Logical/AndExpressionTests.cs @@ -52,5 +52,20 @@ public void TestRightTrueEvaluate() Assert.AreEqual(false, expression.Evaluate(null)); } + + [TestMethod] + public void TestShortCircuit() + { + var rightHandMock = new Mock(); + + var expression = new AndExpression( + Mock.Of(e => e.Evaluate(It.IsAny>()) == (object)false), + rightHandMock.Object, + new Context(ExpressiveOptions.None)); + + expression.Evaluate(null); + + rightHandMock.Verify(e => e.Evaluate(It.IsAny>()), Times.Never); + } } } \ No newline at end of file diff --git a/Source/CSharp/Expressive/Expressive.Tests/Expressions/Binary/Logical/OrExpressionTests.cs b/Source/CSharp/Expressive/Expressive.Tests/Expressions/Binary/Logical/OrExpressionTests.cs index e1b0974..a76f83b 100644 --- a/Source/CSharp/Expressive/Expressive.Tests/Expressions/Binary/Logical/OrExpressionTests.cs +++ b/Source/CSharp/Expressive/Expressive.Tests/Expressions/Binary/Logical/OrExpressionTests.cs @@ -52,5 +52,20 @@ public void TestRightTrueEvaluate() Assert.AreEqual(true, expression.Evaluate(null)); } + + [TestMethod] + public void TestShortCircuit() + { + var rightHandMock = new Mock(); + + var expression = new OrExpression( + Mock.Of(e => e.Evaluate(It.IsAny>()) == (object)true), + rightHandMock.Object, + new Context(ExpressiveOptions.None)); + + expression.Evaluate(null); + + rightHandMock.Verify(e => e.Evaluate(It.IsAny>()), Times.Never); + } } } diff --git a/Source/CSharp/Expressive/Expressive/Expressions/Binary/BinaryExpressionBase.cs b/Source/CSharp/Expressive/Expressive/Expressions/Binary/BinaryExpressionBase.cs index aebdfdb..ba8fd24 100644 --- a/Source/CSharp/Expressive/Expressive/Expressions/Binary/BinaryExpressionBase.cs +++ b/Source/CSharp/Expressive/Expressive/Expressions/Binary/BinaryExpressionBase.cs @@ -49,7 +49,7 @@ public object Evaluate(IDictionary variables) #endregion - private static object CheckAndEvaluateSubExpression(object result, IDictionary variables) + protected static object CheckAndEvaluateSubExpression(object result, IDictionary variables) { if (result is Expression lhsExpression) { diff --git a/Source/CSharp/Expressive/Expressive/Expressions/Binary/Logical/AndExpression.cs b/Source/CSharp/Expressive/Expressive/Expressions/Binary/Logical/AndExpression.cs index 5551f08..5089ec6 100644 --- a/Source/CSharp/Expressive/Expressive/Expressions/Binary/Logical/AndExpression.cs +++ b/Source/CSharp/Expressive/Expressive/Expressions/Binary/Logical/AndExpression.cs @@ -15,10 +15,9 @@ public AndExpression(IExpression lhs, IExpression rhs, Context context) : base(l #region BinaryExpressionBase Members - protected override object EvaluateImpl(object lhsResult, IExpression rightHandSide, IDictionary variables) - { - return this.Evaluate(lhsResult, rightHandSide, variables, (l, r) => Convert.ToBoolean(l) && Convert.ToBoolean(r)); - } + protected override object EvaluateImpl(object lhsResult, IExpression rightHandSide, IDictionary variables) => + Convert.ToBoolean(CheckAndEvaluateSubExpression(lhsResult, variables)) && + Convert.ToBoolean(CheckAndEvaluateSubExpression(rightHandSide.Evaluate(variables), variables)); #endregion } diff --git a/Source/CSharp/Expressive/Expressive/Expressions/Binary/Logical/OrExpression.cs b/Source/CSharp/Expressive/Expressive/Expressions/Binary/Logical/OrExpression.cs index 29fbd6b..eeb559d 100644 --- a/Source/CSharp/Expressive/Expressive/Expressions/Binary/Logical/OrExpression.cs +++ b/Source/CSharp/Expressive/Expressive/Expressions/Binary/Logical/OrExpression.cs @@ -15,10 +15,9 @@ public OrExpression(IExpression lhs, IExpression rhs, Context context) : base(lh #region BinaryExpressionBase Members - protected override object EvaluateImpl(object lhsResult, IExpression rightHandSide, IDictionary variables) - { - return this.Evaluate(lhsResult, rightHandSide, variables, (l, r) => Convert.ToBoolean(l) || Convert.ToBoolean(r)); - } + protected override object EvaluateImpl(object lhsResult, IExpression rightHandSide, IDictionary variables) => + Convert.ToBoolean(CheckAndEvaluateSubExpression(lhsResult, variables)) || + Convert.ToBoolean(CheckAndEvaluateSubExpression(rightHandSide.Evaluate(variables), variables)); #endregion }