/// <summary> /// Creates a <see cref="CatchBlock"/> representing a catch statement with the specified elements. /// </summary> /// <param name="type">The <see cref="Type"/> of <see cref="Exception"/> this <see cref="CatchBlock"/> will handle.</param> /// <param name="variable">A <see cref="ParameterExpression"/> representing a reference to the <see cref="Exception"/> object caught by this handler.</param> /// <param name="body">The body of the catch statement.</param> /// <param name="filter">The body of the <see cref="Exception"/> filter.</param> /// <returns>The created <see cref="CatchBlock"/>.</returns> /// <remarks><paramref name="type"/> must be non-null and match the type of <paramref name="variable"/> (if it is supplied).</remarks> public static CatchBlock MakeCatchBlock(Type type, ParameterExpression variable, Expression body, Expression filter) { ContractUtils.RequiresNotNull(type, nameof(type)); ContractUtils.Requires(variable == null || TypeUtils.AreEquivalent(variable.Type, type), nameof(variable)); if (variable == null) { TypeUtils.ValidateType(type, nameof(type)); if (type.IsByRef) { throw Error.TypeMustNotBeByRef(nameof(type)); } if (type.IsPointer) { throw Error.TypeMustNotBePointer(nameof(type)); } } else if (variable.IsByRef) { throw Error.VariableMustNotBeByRef(variable, variable.Type, nameof(variable)); } ExpressionUtils.RequiresCanRead(body, nameof(body)); if (filter != null) { ExpressionUtils.RequiresCanRead(filter, nameof(filter)); if (filter.Type != typeof(bool)) { throw Error.ArgumentMustBeBoolean(nameof(filter)); } } return(new CatchBlock(type, variable, body, filter)); }
/// <summary> /// Creates a catch block. /// </summary> /// <param name="variables">The variables introduced by the catch block.</param> /// <param name="type">The type of the exceptions to handle.</param> /// <param name="variable">The variable to assign a caught exception to.</param> /// <param name="body">The body of the catch block.</param> /// <param name="filter">The filter to apply.</param> /// <returns>The created <see cref="CSharpCatchBlock"/>.</returns> public static CSharpCatchBlock MakeCatchBlock(IEnumerable <ParameterExpression> variables, Type type, ParameterExpression variable, Expression body, Expression filter) { var variablesList = CheckUniqueVariables(variables, nameof(variables)); Requires(variable == null || AreEquivalent(variable.Type, type), nameof(variable)); if (variable != null) { if (variable.IsByRef) { throw LinqError.VariableMustNotBeByRef(variable, variable.Type); } // REVIEW: See UsingCSharpStatement for a similar situation. if (!variablesList.Contains(variable)) { throw Error.CatchVariableNotInScope(variable); } if (type == null) { type = variable.Type; } else if (!AreEquivalent(type, variable.Type)) { throw Error.CatchTypeNotEquivalentWithVariableType(type, variable.Type); } } else if (type != null) { ValidateType(type); } else { type = typeof(object); // NB: Used to catch all. } RequiresCanRead(body, nameof(body)); if (filter != null) { RequiresCanRead(filter, nameof(filter)); if (filter.Type != typeof(bool)) { throw LinqError.ArgumentMustBeBoolean(); } } return(new CSharpCatchBlock(variablesList, type, variable, body, filter)); }
private static void ValidateCondition(Expression test, bool optionalTest = false) { if (optionalTest && test == null) { return; } // TODO: We can be more flexible and allow the rules in C# spec 7.20. // Note that this behavior is the same as IfThen, but we could also add C# specific nodes for those, // with the more flexible construction behavior. if (test.Type != typeof(bool)) { throw LinqError.ArgumentMustBeBoolean(); } }
/// <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)); }
/// <summary> /// Creates a <see cref="CatchBlock"/> representing a catch statement with the specified elements. /// </summary> /// <param name="type">The <see cref="Type"/> of <see cref="Exception"/> this <see cref="CatchBlock"/> will handle.</param> /// <param name="variable">A <see cref="ParameterExpression"/> representing a reference to the <see cref="Exception"/> object caught by this handler.</param> /// <param name="body">The body of the catch statement.</param> /// <param name="filter">The body of the <see cref="Exception"/> filter.</param> /// <returns>The created <see cref="CatchBlock"/>.</returns> /// <remarks><paramref name="type"/> must be non-null and match the type of <paramref name="variable"/> (if it is supplied).</remarks> public static CatchBlock MakeCatchBlock(Type type, ParameterExpression variable, Expression body, Expression filter) { ContractUtils.RequiresNotNull(type, "type"); ContractUtils.Requires(variable == null || TypeUtils.AreEquivalent(variable.Type, type), "variable"); if (variable != null && variable.IsByRef) { throw Error.VariableMustNotBeByRef(variable, variable.Type); } RequiresCanRead(body, "body"); if (filter != null) { RequiresCanRead(filter, "filter"); if (filter.Type != typeof(bool)) { throw Error.ArgumentMustBeBoolean(); } } return(new CatchBlock(type, variable, body, filter)); }
/// <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)); }
/// <summary> /// Creates a <see cref="ConditionalExpression"/>. /// </summary> /// <param name="test">An <see cref="Expression"/> to set the <see cref="ConditionalExpression.Test"/> property equal to.</param> /// <param name="ifTrue">An <see cref="Expression"/> to set the <see cref="ConditionalExpression.IfTrue"/> property equal to.</param> /// <param name="ifFalse">An <see cref="Expression"/> to set the <see cref="ConditionalExpression.IfFalse"/> property equal to.</param> /// <param name="type">A <see cref="Type"/> to set the <see cref="Type"/> property equal to.</param> /// <returns>A <see cref="ConditionalExpression"/> that has the <see cref="NodeType"/> property equal to /// <see cref="ExpressionType.Conditional"/> and the <see cref="ConditionalExpression.Test"/>, <see cref="ConditionalExpression.IfTrue"/>, /// and <see cref="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="Void"/>.</remarks> public static ConditionalExpression Condition(Expression test, Expression ifTrue, Expression ifFalse, Type type) { ExpressionUtils.RequiresCanRead(test, nameof(test)); ExpressionUtils.RequiresCanRead(ifTrue, nameof(ifTrue)); ExpressionUtils.RequiresCanRead(ifFalse, nameof(ifFalse)); ArgumentNullException.ThrowIfNull(type); if (test.Type != typeof(bool)) { throw Error.ArgumentMustBeBoolean(nameof(test)); } 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)); }