/// <summary> /// Creates a <see cref="ConditionalExpression"/>. /// </summary> /// <param name="test">An <see cref="Expression"/> to set the <see cref="P:ConditionalExpression.Test"/> property equal to.</param> /// <param name="ifTrue">An <see cref="Expression"/> to set the <see cref="P:ConditionalExpression.IfTrue"/> property equal to.</param> /// <param name="ifFalse">An <see cref="Expression"/> to set the <see cref="P:ConditionalExpression.IfFalse"/> property equal to.</param> /// <returns>A <see cref="ConditionalExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to /// <see cref="F:ExpressionType.Conditional"/> and the <see cref="P:ConditionalExpression.Test"/>, <see cref="P:ConditionalExpression.IfTrue"/>, /// and <see cref="P:ConditionalExpression.IfFalse"/> properties set to the specified values.</returns> public static ConditionalExpression Condition(Expression test, Expression ifTrue, Expression ifFalse) { RequiresCanRead(test, "test"); RequiresCanRead(ifTrue, "ifTrue"); RequiresCanRead(ifFalse, "ifFalse"); if (test.Type != typeof(bool)) { throw Error.ArgumentMustBeBoolean(); } if (!TypeUtils.AreEquivalent(ifTrue.Type, ifFalse.Type)) { throw Error.ArgumentTypesMustMatch(); } return(ConditionalExpression.Make(test, ifTrue, ifFalse, ifTrue.Type)); }
// ConditionalExpression private Result RewriteConditionalExpression(Expression expr, Stack stack) { ConditionalExpression node = (ConditionalExpression)expr; // Test executes at the stack as left by parent Result test = RewriteExpression(node.Test, stack); // The test is popped by conditional jump so branches execute // at the stack as left by parent too. Result ifTrue = RewriteExpression(node.IfTrue, stack); Result ifFalse = RewriteExpression(node.IfFalse, stack); RewriteAction action = test.Action | ifTrue.Action | ifFalse.Action; if (action != RewriteAction.None) { expr = ConditionalExpression.Make(test.Node, ifTrue.Node, ifFalse.Node, node.Type); } return(new Result(action, expr)); }
/// <summary> /// Creates a <see cref="ConditionalExpression"/>. /// </summary> /// <param name="test">An <see cref="Expression"/> to set the <see cref="P:ConditionalExpression.Test"/> property equal to.</param> /// <param name="ifTrue">An <see cref="Expression"/> to set the <see cref="P:ConditionalExpression.IfTrue"/> property equal to.</param> /// <param name="ifFalse">An <see cref="Expression"/> to set the <see cref="P:ConditionalExpression.IfFalse"/> property equal to.</param> /// <param name="type">A <see cref="Type"/> to set the <see cref="P:Expression.Type"/> property equal to.</param> /// <returns>A <see cref="ConditionalExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to /// <see cref="F:ExpressionType.Conditional"/> and the <see cref="P:ConditionalExpression.Test"/>, <see cref="P:ConditionalExpression.IfTrue"/>, /// and <see cref="P:ConditionalExpression.IfFalse"/> properties set to the specified values.</returns> /// <remarks>This method allows explicitly unifying the result type of the conditional expression in cases where the types of <paramref name="ifTrue"/> /// and <paramref name="ifFalse"/> expressions are not equal. Types of both <paramref name="ifTrue"/> and <paramref name="ifFalse"/> must be implicitly /// reference assignable to the result type. The <paramref name="type"/> is allowed to be <see cref="System.Void"/>.</remarks> public static ConditionalExpression Condition(Expression test, Expression ifTrue, Expression ifFalse, Type type) { RequiresCanRead(test, "test"); RequiresCanRead(ifTrue, "ifTrue"); RequiresCanRead(ifFalse, "ifFalse"); ContractUtils.RequiresNotNull(type, "type"); if (test.Type != typeof(bool)) { throw Error.ArgumentMustBeBoolean(); } if (type != typeof(void)) { if (!TypeUtils.AreReferenceAssignable(type, ifTrue.Type) || !TypeUtils.AreReferenceAssignable(type, ifFalse.Type)) { throw Error.ArgumentTypesMustMatch(); } } return(ConditionalExpression.Make(test, ifTrue, ifFalse, type)); }