2 /* ****************************************************************************
4 * Copyright (c) Microsoft Corporation.
6 * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
7 * copy of the license can be found in the License.html file at the root of this distribution. If
8 * you cannot locate the Apache License, Version 2.0, please send an email to
9 * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
10 * by the terms of the Apache License, Version 2.0.
12 * You must not remove this notice, or any other, from this software.
15 * ***************************************************************************/
18 using System.Collections.Generic;
19 using System.Diagnostics;
20 using System.Dynamic.Utils;
21 using System.Reflection;
24 namespace Microsoft.Scripting.Ast {
26 namespace System.Linq.Expressions {
30 /// Represents an expression that has a binary operator.
32 [DebuggerTypeProxy(typeof(Expression.BinaryExpressionProxy))]
33 public class BinaryExpression : Expression {
34 private readonly Expression _left;
35 private readonly Expression _right;
37 internal BinaryExpression(Expression left, Expression right) {
43 /// Gets a value that indicates whether the expression tree node can be reduced.
45 public override bool CanReduce {
47 // Only OpAssignments are reducible.
48 return IsOpAssignment(NodeType);
52 private static bool IsOpAssignment(ExpressionType op) {
54 case ExpressionType.AddAssign:
55 case ExpressionType.SubtractAssign:
56 case ExpressionType.MultiplyAssign:
57 case ExpressionType.AddAssignChecked:
58 case ExpressionType.SubtractAssignChecked:
59 case ExpressionType.MultiplyAssignChecked:
60 case ExpressionType.DivideAssign:
61 case ExpressionType.ModuloAssign:
62 case ExpressionType.PowerAssign:
63 case ExpressionType.AndAssign:
64 case ExpressionType.OrAssign:
65 case ExpressionType.RightShiftAssign:
66 case ExpressionType.LeftShiftAssign:
67 case ExpressionType.ExclusiveOrAssign:
74 /// Gets the right operand of the binary operation.
76 public Expression Right {
77 get { return _right; }
81 /// Gets the left operand of the binary operation.
83 public Expression Left {
88 /// Gets the implementing method for the binary operation.
90 public MethodInfo Method {
91 get { return GetMethod(); }
94 internal virtual MethodInfo GetMethod() {
98 // Note: takes children in evaluation order, which is also the order
99 // that ExpressionVisitor visits them. Having them this way reduces the
100 // chances people will make a mistake and use an inconsistent order in
104 /// Creates a new expression that is like this one, but using the
105 /// supplied children. If all of the children are the same, it will
106 /// return this expression.
108 /// <param name="left">The <see cref="Left" /> property of the result.</param>
109 /// <param name="conversion">The <see cref="Conversion" /> property of the result.</param>
110 /// <param name="right">The <see cref="Right" /> property of the result.</param>
111 /// <returns>This expression if no children changed, or an expression with the updated children.</returns>
112 public BinaryExpression Update(Expression left, LambdaExpression conversion, Expression right) {
113 if (left == Left && right == Right && conversion == Conversion) {
116 if (IsReferenceComparison) {
117 if (NodeType == ExpressionType.Equal) {
118 return Expression.ReferenceEqual(left, right);
120 return Expression.ReferenceNotEqual(left, right);
123 return Expression.MakeBinary(NodeType, left, right, IsLiftedToNull, Method, conversion);
127 /// Reduces the binary expression node to a simpler expression.
128 /// If CanReduce returns true, this should return a valid expression.
129 /// This method is allowed to return another node which itself
132 /// <returns>The reduced expression.</returns>
133 public override Expression Reduce() {
134 // Only reduce OpAssignment expressions.
135 if (IsOpAssignment(NodeType)) {
136 switch (_left.NodeType) {
137 case ExpressionType.MemberAccess:
138 return ReduceMember();
140 case ExpressionType.Index:
141 return ReduceIndex();
144 return ReduceVariable();
150 // Return the corresponding Op of an assignment op.
151 private static ExpressionType GetBinaryOpFromAssignmentOp(ExpressionType op) {
152 Debug.Assert(IsOpAssignment(op));
154 case ExpressionType.AddAssign:
155 return ExpressionType.Add;
156 case ExpressionType.AddAssignChecked:
157 return ExpressionType.AddChecked;
158 case ExpressionType.SubtractAssign:
159 return ExpressionType.Subtract;
160 case ExpressionType.SubtractAssignChecked:
161 return ExpressionType.SubtractChecked;
162 case ExpressionType.MultiplyAssign:
163 return ExpressionType.Multiply;
164 case ExpressionType.MultiplyAssignChecked:
165 return ExpressionType.MultiplyChecked;
166 case ExpressionType.DivideAssign:
167 return ExpressionType.Divide;
168 case ExpressionType.ModuloAssign:
169 return ExpressionType.Modulo;
170 case ExpressionType.PowerAssign:
171 return ExpressionType.Power;
172 case ExpressionType.AndAssign:
173 return ExpressionType.And;
174 case ExpressionType.OrAssign:
175 return ExpressionType.Or;
176 case ExpressionType.RightShiftAssign:
177 return ExpressionType.RightShift;
178 case ExpressionType.LeftShiftAssign:
179 return ExpressionType.LeftShift;
180 case ExpressionType.ExclusiveOrAssign:
181 return ExpressionType.ExclusiveOr;
184 throw Error.InvalidOperation("op");
189 private Expression ReduceVariable() {
191 // ... is reduced into ...
193 ExpressionType op = GetBinaryOpFromAssignmentOp(NodeType);
194 Expression r = Expression.MakeBinary(op, _left, _right, false, Method);
195 LambdaExpression conversion = GetConversion();
196 if (conversion != null) {
197 r = Expression.Invoke(conversion, r);
199 return Expression.Assign(_left, r);
202 private Expression ReduceMember() {
203 MemberExpression member = (MemberExpression)_left;
205 if (member.Expression == null) {
206 // static member, reduce the same as variable
207 return ReduceVariable();
210 // ... is reduced into ...
212 // temp2 = temp1.b (op) r
215 ParameterExpression temp1 = Variable(member.Expression.Type, "temp1");
218 Expression e1 = Expression.Assign(temp1, member.Expression);
220 // 2. temp2 = temp1.b (op) r
221 ExpressionType op = GetBinaryOpFromAssignmentOp(NodeType);
222 Expression e2 = Expression.MakeBinary(op, Expression.MakeMemberAccess(temp1, member.Member), _right, false, Method);
223 LambdaExpression conversion = GetConversion();
224 if (conversion != null) {
225 e2 = Expression.Invoke(conversion, e2);
227 ParameterExpression temp2 = Variable(e2.Type, "temp2");
228 e2 = Expression.Assign(temp2, e2);
230 // 3. temp1.b = temp2
231 Expression e3 = Expression.Assign(Expression.MakeMemberAccess(temp1, member.Member), temp2);
234 Expression e4 = temp2;
236 return Expression.Block(
237 new ParameterExpression[] { temp1, temp2 },
243 private Expression ReduceIndex() {
244 // left[a0, a1, ... aN] (op)= r
246 // ... is reduced into ...
252 // tempValue = tempObj[tempArg0, ... tempArgN] (op) r
253 // tempObj[tempArg0, ... tempArgN] = tempValue
255 var index = (IndexExpression)_left;
257 var vars = new List<ParameterExpression>(index.Arguments.Count + 2);
258 var exprs = new List<Expression>(index.Arguments.Count + 3);
260 var tempObj = Expression.Variable(index.Object.Type, "tempObj");
262 exprs.Add(Expression.Assign(tempObj, index.Object));
264 var tempArgs = new List<Expression>(index.Arguments.Count);
265 foreach (var arg in index.Arguments) {
266 var tempArg = Expression.Variable(arg.Type, "tempArg" + tempArgs.Count);
268 tempArgs.Add(tempArg);
269 exprs.Add(Expression.Assign(tempArg, arg));
272 var tempIndex = Expression.MakeIndex(tempObj, index.Indexer, tempArgs);
274 // tempValue = tempObj[tempArg0, ... tempArgN] (op) r
275 ExpressionType binaryOp = GetBinaryOpFromAssignmentOp(NodeType);
276 Expression op = Expression.MakeBinary(binaryOp, tempIndex, _right, false, Method);
277 LambdaExpression conversion = GetConversion();
278 if (conversion != null) {
279 op = Expression.Invoke(conversion, op);
281 var tempValue = Expression.Variable(op.Type, "tempValue");
283 exprs.Add(Expression.Assign(tempValue, op));
285 // tempObj[tempArg0, ... tempArgN] = tempValue
286 exprs.Add(Expression.Assign(tempIndex, tempValue));
288 return Expression.Block(vars, exprs);
292 /// Gets the type conversion function that is used by a coalescing or compound assignment operation.
294 public LambdaExpression Conversion {
295 get { return GetConversion(); }
298 internal virtual LambdaExpression GetConversion() {
303 /// Gets a value that indicates whether the expression tree node represents a lifted call to an operator.
305 public bool IsLifted {
307 if (NodeType == ExpressionType.Coalesce || NodeType == ExpressionType.Assign) {
310 if (TypeUtils.IsNullableType(_left.Type)) {
311 MethodInfo method = GetMethod();
312 return method == null ||
313 !TypeUtils.AreEquivalent(method.GetParametersCached()[0].ParameterType.GetNonRefType(), _left.Type);
319 /// Gets a value that indicates whether the expression tree node represents a lifted call to an operator whose return type is lifted to a nullable type.
321 public bool IsLiftedToNull {
323 return IsLifted && TypeUtils.IsNullableType(Type);
328 /// Dispatches to the specific visit method for this node type.
330 protected internal override Expression Accept(ExpressionVisitor visitor) {
331 return visitor.VisitBinary(this);
334 internal static Expression Create(ExpressionType nodeType, Expression left, Expression right, Type type, MethodInfo method, LambdaExpression conversion) {
335 if (nodeType == ExpressionType.Assign) {
336 Debug.Assert(method == null && TypeUtils.AreEquivalent(type, left.Type));
337 return new AssignBinaryExpression(left, right);
339 if (conversion != null) {
340 Debug.Assert(method == null && TypeUtils.AreEquivalent(type, right.Type) && nodeType == ExpressionType.Coalesce);
341 return new CoalesceConversionBinaryExpression(left, right, conversion);
343 if (method != null) {
344 return new MethodBinaryExpression(nodeType, left, right, type, method);
346 if (type == typeof(bool)) {
347 return new LogicalBinaryExpression(nodeType, left, right);
349 return new SimpleBinaryExpression(nodeType, left, right, type);
352 internal bool IsLiftedLogical {
354 Type left = _left.Type;
355 Type right = _right.Type;
356 MethodInfo method = GetMethod();
357 ExpressionType kind = NodeType;
360 (kind == ExpressionType.AndAlso || kind == ExpressionType.OrElse) &&
361 TypeUtils.AreEquivalent(right, left) &&
362 TypeUtils.IsNullableType(left) &&
364 TypeUtils.AreEquivalent(method.ReturnType, TypeUtils.GetNonNullableType(left));
368 internal bool IsReferenceComparison {
370 Type left = _left.Type;
371 Type right = _right.Type;
372 MethodInfo method = GetMethod();
373 ExpressionType kind = NodeType;
375 return (kind == ExpressionType.Equal || kind == ExpressionType.NotEqual) &&
376 method == null && !left.IsValueType && !right.IsValueType;
381 // For a userdefined type T which has op_False defined and L, R are
382 // nullable, (L AndAlso R) is computed as:
385 // ? T.op_False(L.GetValueOrDefault())
388 // ? (T?)(T.op_BitwiseAnd(L.GetValueOrDefault(), R.GetValueOrDefault()))
392 // For a userdefined type T which has op_True defined and L, R are
393 // nullable, (L OrElse R) is computed as:
396 // ? T.op_True(L.GetValueOrDefault())
399 // ? (T?)(T.op_BitwiseOr(L.GetValueOrDefault(), R.GetValueOrDefault()))
404 // This is the same behavior as VB. If you think about it, it makes
405 // sense: it's combining the normal pattern for short-circuiting
406 // operators, with the normal pattern for lifted operations: if either
407 // of the operands is null, the result is also null.
409 internal Expression ReduceUserdefinedLifted() {
410 Debug.Assert(IsLiftedLogical);
412 var left = Parameter(_left.Type, "left");
413 var right = Parameter(Right.Type, "right");
414 string opName = NodeType == ExpressionType.AndAlso ? "op_False" : "op_True";
415 MethodInfo opTrueFalse = TypeUtils.GetBooleanOperator(Method.DeclaringType, opName);
416 Debug.Assert(opTrueFalse != null);
422 Property(left, "HasValue"),
424 Call(opTrueFalse, Call(left, "GetValueOrDefault", null)),
428 Assign(right, _right),
430 Property(right, "HasValue"),
434 Call(left, "GetValueOrDefault", null),
435 Call(right, "GetValueOrDefault", null)
449 // Optimized representation of simple logical expressions:
450 // && || == != > < >= <=
451 internal sealed class LogicalBinaryExpression : BinaryExpression {
452 private readonly ExpressionType _nodeType;
454 internal LogicalBinaryExpression(ExpressionType nodeType, Expression left, Expression right)
455 : base(left, right) {
456 _nodeType = nodeType;
459 public sealed override Type Type {
460 get { return typeof(bool); }
463 public sealed override ExpressionType NodeType {
464 get { return _nodeType; }
468 // Optimized assignment node, only holds onto children
469 internal sealed class AssignBinaryExpression : BinaryExpression {
470 internal AssignBinaryExpression(Expression left, Expression right)
471 : base(left, right) {
474 public sealed override Type Type {
475 get { return Left.Type; }
478 public sealed override ExpressionType NodeType {
479 get { return ExpressionType.Assign; }
483 // Coalesce with conversion
484 // This is not a frequently used node, but rather we want to save every
485 // other BinaryExpression from holding onto the null conversion lambda
486 internal sealed class CoalesceConversionBinaryExpression : BinaryExpression {
487 private readonly LambdaExpression _conversion;
489 internal CoalesceConversionBinaryExpression(Expression left, Expression right, LambdaExpression conversion)
490 : base(left, right) {
491 _conversion = conversion;
494 internal override LambdaExpression GetConversion() {
498 public sealed override ExpressionType NodeType {
499 get { return ExpressionType.Coalesce; }
502 public sealed override Type Type {
503 get { return Right.Type; }
507 // OpAssign with conversion
508 // This is not a frequently used node, but rather we want to save every
509 // other BinaryExpression from holding onto the null conversion lambda
510 internal sealed class OpAssignMethodConversionBinaryExpression : MethodBinaryExpression {
511 private readonly LambdaExpression _conversion;
513 internal OpAssignMethodConversionBinaryExpression(ExpressionType nodeType, Expression left, Expression right, Type type, MethodInfo method, LambdaExpression conversion)
514 : base(nodeType, left, right, type, method) {
515 _conversion = conversion;
518 internal override LambdaExpression GetConversion() {
523 // Class that handles most binary expressions
524 // If needed, it can be optimized even more (often Type == left.Type)
525 internal class SimpleBinaryExpression : BinaryExpression {
526 private readonly ExpressionType _nodeType;
527 private readonly Type _type;
529 internal SimpleBinaryExpression(ExpressionType nodeType, Expression left, Expression right, Type type)
530 : base(left, right) {
531 _nodeType = nodeType;
535 public sealed override ExpressionType NodeType {
536 get { return _nodeType; }
539 public sealed override Type Type {
540 get { return _type; }
544 // Class that handles binary expressions with a method
545 // If needed, it can be optimized even more (often Type == method.ReturnType)
546 internal class MethodBinaryExpression : SimpleBinaryExpression {
547 private readonly MethodInfo _method;
549 internal MethodBinaryExpression(ExpressionType nodeType, Expression left, Expression right, Type type, MethodInfo method)
550 : base(nodeType, left, right, type) {
554 internal override MethodInfo GetMethod() {
559 public partial class Expression {
564 /// Creates a <see cref="BinaryExpression"/> that represents an assignment operation.
566 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
567 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
568 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see ref="F:ExpressionType.Assign"/>
569 /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.
571 public static BinaryExpression Assign(Expression left, Expression right) {
572 RequiresCanWrite(left, "left");
573 RequiresCanRead(right, "right");
574 TypeUtils.ValidateType(left.Type);
575 TypeUtils.ValidateType(right.Type);
576 if (!TypeUtils.AreReferenceAssignable(left.Type, right.Type)) {
577 throw Error.ExpressionTypeDoesNotMatchAssignment(right.Type, left.Type);
579 return new AssignBinaryExpression(left, right);
585 private static BinaryExpression GetUserDefinedBinaryOperator(ExpressionType binaryType, string name, Expression left, Expression right, bool liftToNull) {
586 // try exact match first
587 MethodInfo method = GetUserDefinedBinaryOperator(binaryType, left.Type, right.Type, name);
588 if (method != null) {
589 return new MethodBinaryExpression(binaryType, left, right, method.ReturnType, method);
592 if (TypeUtils.IsNullableType(left.Type) && TypeUtils.IsNullableType(right.Type)) {
593 Type nnLeftType = TypeUtils.GetNonNullableType(left.Type);
594 Type nnRightType = TypeUtils.GetNonNullableType(right.Type);
595 method = GetUserDefinedBinaryOperator(binaryType, nnLeftType, nnRightType, name);
596 if (method != null && method.ReturnType.IsValueType && !TypeUtils.IsNullableType(method.ReturnType)) {
597 if (method.ReturnType != typeof(bool) || liftToNull) {
598 return new MethodBinaryExpression(binaryType, left, right, TypeUtils.GetNullableType(method.ReturnType), method);
600 return new MethodBinaryExpression(binaryType, left, right, typeof(bool), method);
608 private static BinaryExpression GetMethodBasedBinaryOperator(ExpressionType binaryType, Expression left, Expression right, MethodInfo method, bool liftToNull) {
609 System.Diagnostics.Debug.Assert(method != null);
610 ValidateOperator(method);
611 ParameterInfo[] pms = method.GetParametersCached();
613 throw Error.IncorrectNumberOfMethodCallArguments(method);
614 if (ParameterIsAssignable(pms[0], left.Type) && ParameterIsAssignable(pms[1], right.Type)) {
615 ValidateParamswithOperandsOrThrow(pms[0].ParameterType, left.Type, binaryType, method.Name);
616 ValidateParamswithOperandsOrThrow(pms[1].ParameterType, right.Type, binaryType, method.Name);
617 return new MethodBinaryExpression(binaryType, left, right, method.ReturnType, method);
620 // check for lifted call
621 if (TypeUtils.IsNullableType(left.Type) && TypeUtils.IsNullableType(right.Type) &&
622 ParameterIsAssignable(pms[0], TypeUtils.GetNonNullableType(left.Type)) &&
623 ParameterIsAssignable(pms[1], TypeUtils.GetNonNullableType(right.Type)) &&
624 method.ReturnType.IsValueType && !TypeUtils.IsNullableType(method.ReturnType)) {
625 if (method.ReturnType != typeof(bool) || liftToNull) {
626 return new MethodBinaryExpression(binaryType, left, right, TypeUtils.GetNullableType(method.ReturnType), method);
628 return new MethodBinaryExpression(binaryType, left, right, typeof(bool), method);
631 throw Error.OperandTypesDoNotMatchParameters(binaryType, method.Name);
634 private static BinaryExpression GetMethodBasedAssignOperator(ExpressionType binaryType, Expression left, Expression right, MethodInfo method, LambdaExpression conversion, bool liftToNull) {
635 BinaryExpression b = GetMethodBasedBinaryOperator(binaryType, left, right, method, liftToNull);
636 if (conversion == null) {
637 // return type must be assignable back to the left type
638 if (!TypeUtils.AreReferenceAssignable(left.Type, b.Type)) {
639 throw Error.UserDefinedOpMustHaveValidReturnType(binaryType, b.Method.Name);
642 // add the conversion to the result
643 ValidateOpAssignConversionLambda(conversion, b.Left, b.Method, b.NodeType);
644 b = new OpAssignMethodConversionBinaryExpression(b.NodeType, b.Left, b.Right, b.Left.Type, b.Method, conversion);
650 private static BinaryExpression GetUserDefinedBinaryOperatorOrThrow(ExpressionType binaryType, string name, Expression left, Expression right, bool liftToNull) {
651 BinaryExpression b = GetUserDefinedBinaryOperator(binaryType, name, left, right, liftToNull);
653 ParameterInfo[] pis = b.Method.GetParametersCached();
654 ValidateParamswithOperandsOrThrow(pis[0].ParameterType, left.Type, binaryType, name);
655 ValidateParamswithOperandsOrThrow(pis[1].ParameterType, right.Type, binaryType, name);
658 throw Error.BinaryOperatorNotDefined(binaryType, left.Type, right.Type);
661 private static BinaryExpression GetUserDefinedAssignOperatorOrThrow(ExpressionType binaryType, string name, Expression left, Expression right, LambdaExpression conversion, bool liftToNull) {
662 BinaryExpression b = GetUserDefinedBinaryOperatorOrThrow(binaryType, name, left, right, liftToNull);
663 if (conversion == null) {
664 // return type must be assignable back to the left type
665 if (!TypeUtils.AreReferenceAssignable(left.Type, b.Type)) {
666 throw Error.UserDefinedOpMustHaveValidReturnType(binaryType, b.Method.Name);
669 // add the conversion to the result
670 ValidateOpAssignConversionLambda(conversion, b.Left, b.Method, b.NodeType);
671 b = new OpAssignMethodConversionBinaryExpression(b.NodeType, b.Left, b.Right, b.Left.Type, b.Method, conversion);
677 private static MethodInfo GetUserDefinedBinaryOperator(ExpressionType binaryType, Type leftType, Type rightType, string name) {
678 // UNDONE: This algorithm is wrong, we should be checking for uniqueness and erroring if
679 // UNDONE: it is defined on both types.
680 Type[] types = new Type[] { leftType, rightType };
681 Type nnLeftType = TypeUtils.GetNonNullableType(leftType);
682 Type nnRightType = TypeUtils.GetNonNullableType(rightType);
683 BindingFlags flags = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
684 MethodInfo method = nnLeftType.GetMethodValidated(name, flags, null, types, null);
685 if (method == null && !TypeUtils.AreEquivalent(leftType, rightType)) {
686 method = nnRightType.GetMethodValidated(name, flags, null, types, null);
689 if (IsLiftingConditionalLogicalOperator(leftType, rightType, method, binaryType)) {
690 method = GetUserDefinedBinaryOperator(binaryType, nnLeftType, nnRightType, name);
696 private static bool IsLiftingConditionalLogicalOperator(Type left, Type right, MethodInfo method, ExpressionType binaryType) {
697 return TypeUtils.IsNullableType(right) &&
698 TypeUtils.IsNullableType(left) &&
700 (binaryType == ExpressionType.AndAlso || binaryType == ExpressionType.OrElse);
704 internal static bool ParameterIsAssignable(ParameterInfo pi, Type argType) {
705 Type pType = pi.ParameterType;
707 pType = pType.GetElementType();
708 return TypeUtils.AreReferenceAssignable(pType, argType);
712 private static void ValidateParamswithOperandsOrThrow(Type paramType, Type operandType, ExpressionType exprType, string name) {
713 if (TypeUtils.IsNullableType(paramType) && !TypeUtils.IsNullableType(operandType)) {
714 throw Error.OperandTypesDoNotMatchParameters(exprType, name);
719 private static void ValidateOperator(MethodInfo method) {
720 System.Diagnostics.Debug.Assert(method != null);
721 ValidateMethodInfo(method);
722 if (!method.IsStatic)
723 throw Error.UserDefinedOperatorMustBeStatic(method);
724 if (method.ReturnType == typeof(void))
725 throw Error.UserDefinedOperatorMustNotBeVoid(method);
729 private static void ValidateMethodInfo(MethodInfo method) {
730 if (method.IsGenericMethodDefinition)
731 throw Error.MethodIsGeneric(method);
732 if (method.ContainsGenericParameters)
733 throw Error.MethodContainsGenericParameters(method);
737 private static bool IsNullComparison(Expression left, Expression right) {
738 // If we have x==null, x!=null, null==x or null!=x where x is
739 // nullable but not null, then this is treated as a call to x.HasValue
740 // and is legal even if there is no equality operator defined on the
742 if (IsNullConstant(left) && !IsNullConstant(right) && TypeUtils.IsNullableType(right.Type)) {
745 if (IsNullConstant(right) && !IsNullConstant(left) && TypeUtils.IsNullableType(left.Type)) {
752 // Note: this has different meaning than ConstantCheck.IsNull
753 // That function attempts to determine if the result of a tree will be
754 // null at runtime. This function is used at tree construction time and
755 // only looks for a ConstantExpression with a null Value. It can't
756 // become "smarter" or that would break tree construction.
757 private static bool IsNullConstant(Expression e) {
758 var c = e as ConstantExpression;
759 return c != null && c.Value == null;
763 private static void ValidateUserDefinedConditionalLogicOperator(ExpressionType nodeType, Type left, Type right, MethodInfo method) {
764 ValidateOperator(method);
765 ParameterInfo[] pms = method.GetParametersCached();
767 throw Error.IncorrectNumberOfMethodCallArguments(method);
768 if (!ParameterIsAssignable(pms[0], left)) {
769 if (!(TypeUtils.IsNullableType(left) && ParameterIsAssignable(pms[0], TypeUtils.GetNonNullableType(left))))
770 throw Error.OperandTypesDoNotMatchParameters(nodeType, method.Name);
772 if (!ParameterIsAssignable(pms[1], right)) {
773 if (!(TypeUtils.IsNullableType(right) && ParameterIsAssignable(pms[1], TypeUtils.GetNonNullableType(right))))
774 throw Error.OperandTypesDoNotMatchParameters(nodeType, method.Name);
776 if (pms[0].ParameterType != pms[1].ParameterType) {
777 throw Error.UserDefinedOpMustHaveConsistentTypes(nodeType, method.Name);
779 if (method.ReturnType != pms[0].ParameterType) {
780 throw Error.UserDefinedOpMustHaveConsistentTypes(nodeType, method.Name);
782 if (IsValidLiftedConditionalLogicalOperator(left, right, pms)) {
783 left = TypeUtils.GetNonNullableType(left);
784 right = TypeUtils.GetNonNullableType(left);
786 MethodInfo opTrue = TypeUtils.GetBooleanOperator(method.DeclaringType, "op_True");
787 MethodInfo opFalse = TypeUtils.GetBooleanOperator(method.DeclaringType, "op_False");
788 if (opTrue == null || opTrue.ReturnType != typeof(bool) ||
789 opFalse == null || opFalse.ReturnType != typeof(bool)) {
790 throw Error.LogicalOperatorMustHaveBooleanOperators(nodeType, method.Name);
792 VerifyOpTrueFalse(nodeType, left, opFalse);
793 VerifyOpTrueFalse(nodeType, left, opTrue);
796 private static void VerifyOpTrueFalse(ExpressionType nodeType, Type left, MethodInfo opTrue) {
797 ParameterInfo[] pmsOpTrue = opTrue.GetParametersCached();
798 if (pmsOpTrue.Length != 1)
799 throw Error.IncorrectNumberOfMethodCallArguments(opTrue);
801 if (!ParameterIsAssignable(pmsOpTrue[0], left)) {
802 if (!(TypeUtils.IsNullableType(left) && ParameterIsAssignable(pmsOpTrue[0], TypeUtils.GetNonNullableType(left))))
803 throw Error.OperandTypesDoNotMatchParameters(nodeType, opTrue.Name);
807 private static bool IsValidLiftedConditionalLogicalOperator(Type left, Type right, ParameterInfo[] pms) {
808 return TypeUtils.AreEquivalent(left, right) &&
809 TypeUtils.IsNullableType(right) &&
810 TypeUtils.AreEquivalent(pms[1].ParameterType, TypeUtils.GetNonNullableType(right));
815 /// Creates a BinaryExpression, given the left and right operands, by calling an appropriate factory method.
817 /// <param name="binaryType">The ExpressionType that specifies the type of binary operation.</param>
818 /// <param name="left">An Expression that represents the left operand.</param>
819 /// <param name="right">An Expression that represents the right operand.</param>
820 /// <returns>The BinaryExpression that results from calling the appropriate factory method.</returns>
821 public static BinaryExpression MakeBinary(ExpressionType binaryType, Expression left, Expression right) {
822 return MakeBinary(binaryType, left, right, false, null, null);
826 /// Creates a BinaryExpression, given the left and right operands, by calling an appropriate factory method.
828 /// <param name="binaryType">The ExpressionType that specifies the type of binary operation.</param>
829 /// <param name="left">An Expression that represents the left operand.</param>
830 /// <param name="right">An Expression that represents the right operand.</param>
831 /// <param name="liftToNull">true to set IsLiftedToNull to true; false to set IsLiftedToNull to false.</param>
832 /// <param name="method">A MethodInfo that specifies the implementing method.</param>
833 /// <returns>The BinaryExpression that results from calling the appropriate factory method.</returns>
834 public static BinaryExpression MakeBinary(ExpressionType binaryType, Expression left, Expression right, bool liftToNull, MethodInfo method) {
835 return MakeBinary(binaryType, left, right, liftToNull, method, null);
840 /// Creates a BinaryExpression, given the left and right operands, by calling an appropriate factory method.
842 /// <param name="binaryType">The ExpressionType that specifies the type of binary operation.</param>
843 /// <param name="left">An Expression that represents the left operand.</param>
844 /// <param name="right">An Expression that represents the right operand.</param>
845 /// <param name="liftToNull">true to set IsLiftedToNull to true; false to set IsLiftedToNull to false.</param>
846 /// <param name="method">A MethodInfo that specifies the implementing method.</param>
847 /// <param name="conversion">A LambdaExpression that represents a type conversion function. This parameter is used if binaryType is Coalesce or compound assignment.</param>
848 /// <returns>The BinaryExpression that results from calling the appropriate factory method.</returns>
849 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
850 public static BinaryExpression MakeBinary(ExpressionType binaryType, Expression left, Expression right, bool liftToNull, MethodInfo method, LambdaExpression conversion) {
851 switch (binaryType) {
852 case ExpressionType.Add:
853 return Add(left, right, method);
854 case ExpressionType.AddChecked:
855 return AddChecked(left, right, method);
856 case ExpressionType.Subtract:
857 return Subtract(left, right, method);
858 case ExpressionType.SubtractChecked:
859 return SubtractChecked(left, right, method);
860 case ExpressionType.Multiply:
861 return Multiply(left, right, method);
862 case ExpressionType.MultiplyChecked:
863 return MultiplyChecked(left, right, method);
864 case ExpressionType.Divide:
865 return Divide(left, right, method);
866 case ExpressionType.Modulo:
867 return Modulo(left, right, method);
868 case ExpressionType.Power:
869 return Power(left, right, method);
870 case ExpressionType.And:
871 return And(left, right, method);
872 case ExpressionType.AndAlso:
873 return AndAlso(left, right, method);
874 case ExpressionType.Or:
875 return Or(left, right, method);
876 case ExpressionType.OrElse:
877 return OrElse(left, right, method);
878 case ExpressionType.LessThan:
879 return LessThan(left, right, liftToNull, method);
880 case ExpressionType.LessThanOrEqual:
881 return LessThanOrEqual(left, right, liftToNull, method);
882 case ExpressionType.GreaterThan:
883 return GreaterThan(left, right, liftToNull, method);
884 case ExpressionType.GreaterThanOrEqual:
885 return GreaterThanOrEqual(left, right, liftToNull, method);
886 case ExpressionType.Equal:
887 return Equal(left, right, liftToNull, method);
888 case ExpressionType.NotEqual:
889 return NotEqual(left, right, liftToNull, method);
890 case ExpressionType.ExclusiveOr:
891 return ExclusiveOr(left, right, method);
892 case ExpressionType.Coalesce:
893 return Coalesce(left, right, conversion);
894 case ExpressionType.ArrayIndex:
895 return ArrayIndex(left, right);
896 case ExpressionType.RightShift:
897 return RightShift(left, right, method);
898 case ExpressionType.LeftShift:
899 return LeftShift(left, right, method);
900 case ExpressionType.Assign:
901 return Assign(left, right);
902 case ExpressionType.AddAssign:
903 return AddAssign(left, right, method, conversion);
904 case ExpressionType.AndAssign:
905 return AndAssign(left, right, method, conversion);
906 case ExpressionType.DivideAssign:
907 return DivideAssign(left, right, method, conversion);
908 case ExpressionType.ExclusiveOrAssign:
909 return ExclusiveOrAssign(left, right, method, conversion);
910 case ExpressionType.LeftShiftAssign:
911 return LeftShiftAssign(left, right, method, conversion);
912 case ExpressionType.ModuloAssign:
913 return ModuloAssign(left, right, method, conversion);
914 case ExpressionType.MultiplyAssign:
915 return MultiplyAssign(left, right, method, conversion);
916 case ExpressionType.OrAssign:
917 return OrAssign(left, right, method, conversion);
918 case ExpressionType.PowerAssign:
919 return PowerAssign(left, right, method, conversion);
920 case ExpressionType.RightShiftAssign:
921 return RightShiftAssign(left, right, method, conversion);
922 case ExpressionType.SubtractAssign:
923 return SubtractAssign(left, right, method, conversion);
924 case ExpressionType.AddAssignChecked:
925 return AddAssignChecked(left, right, method, conversion);
926 case ExpressionType.SubtractAssignChecked:
927 return SubtractAssignChecked(left, right, method, conversion);
928 case ExpressionType.MultiplyAssignChecked:
929 return MultiplyAssignChecked(left, right, method, conversion);
931 throw Error.UnhandledBinary(binaryType);
935 #region Equality Operators
939 /// Creates a <see cref="BinaryExpression"/> that represents an equality comparison.
941 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
942 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
943 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.Equal"/>
944 /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
945 public static BinaryExpression Equal(Expression left, Expression right) {
946 return Equal(left, right, false, null);
950 /// Creates a <see cref="BinaryExpression"/> that represents an equality comparison.
952 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
953 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
954 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
955 /// <param name="liftToNull">true to set IsLiftedToNull to true; false to set IsLiftedToNull to false.</param>
956 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.Equal"/>
957 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, <see cref="P:BinaryExpression.IsLiftedToNull"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
959 public static BinaryExpression Equal(Expression left, Expression right, bool liftToNull, MethodInfo method) {
960 RequiresCanRead(left, "left");
961 RequiresCanRead(right, "right");
962 if (method == null) {
963 return GetEqualityComparisonOperator(ExpressionType.Equal, "op_Equality", left, right, liftToNull);
965 return GetMethodBasedBinaryOperator(ExpressionType.Equal, left, right, method, liftToNull);
969 /// Creates a <see cref="BinaryExpression"/> that represents a reference equality comparison.
971 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
972 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
973 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.Equal"/>
974 /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.
976 public static BinaryExpression ReferenceEqual(Expression left, Expression right) {
977 RequiresCanRead(left, "left");
978 RequiresCanRead(right, "right");
979 if (TypeUtils.HasReferenceEquality(left.Type, right.Type)) {
980 return new LogicalBinaryExpression(ExpressionType.Equal, left, right);
982 throw Error.ReferenceEqualityNotDefined(left.Type, right.Type);
986 /// Creates a <see cref="BinaryExpression"/> that represents an inequality comparison.
988 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
989 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
990 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.NotEqual"/>
991 /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
992 public static BinaryExpression NotEqual(Expression left, Expression right) {
993 return NotEqual(left, right, false, null);
997 /// Creates a <see cref="BinaryExpression"/> that represents an inequality comparison.
999 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1000 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1001 /// <param name="liftToNull">true to set IsLiftedToNull to true; false to set IsLiftedToNull to false.</param>
1002 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
1003 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.NotEqual"/>
1004 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, <see cref="P:BinaryExpression.IsLiftedToNull"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
1006 public static BinaryExpression NotEqual(Expression left, Expression right, bool liftToNull, MethodInfo method) {
1007 RequiresCanRead(left, "left");
1008 RequiresCanRead(right, "right");
1009 if (method == null) {
1010 return GetEqualityComparisonOperator(ExpressionType.NotEqual, "op_Inequality", left, right, liftToNull);
1012 return GetMethodBasedBinaryOperator(ExpressionType.NotEqual, left, right, method, liftToNull);
1016 /// Creates a <see cref="BinaryExpression"/> that represents a reference inequality comparison.
1018 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1019 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1020 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.NotEqual"/>
1021 /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.
1023 public static BinaryExpression ReferenceNotEqual(Expression left, Expression right) {
1024 RequiresCanRead(left, "left");
1025 RequiresCanRead(right, "right");
1026 if (TypeUtils.HasReferenceEquality(left.Type, right.Type)) {
1027 return new LogicalBinaryExpression(ExpressionType.NotEqual, left, right);
1029 throw Error.ReferenceEqualityNotDefined(left.Type, right.Type);
1032 private static BinaryExpression GetEqualityComparisonOperator(ExpressionType binaryType, string opName, Expression left, Expression right, bool liftToNull) {
1033 // known comparison - numeric types, bools, object, enums
1034 if (left.Type == right.Type && (TypeUtils.IsNumeric(left.Type) ||
1035 left.Type == typeof(object) ||
1036 TypeUtils.IsBool(left.Type) ||
1037 TypeUtils.GetNonNullableType(left.Type).IsEnum)) {
1038 if (TypeUtils.IsNullableType(left.Type) && liftToNull) {
1039 return new SimpleBinaryExpression(binaryType, left, right, typeof(bool?));
1041 return new LogicalBinaryExpression(binaryType, left, right);
1044 // look for user defined operator
1045 BinaryExpression b = GetUserDefinedBinaryOperator(binaryType, opName, left, right, liftToNull);
1049 if (TypeUtils.HasBuiltInEqualityOperator(left.Type, right.Type) || IsNullComparison(left, right)) {
1050 if (TypeUtils.IsNullableType(left.Type) && liftToNull) {
1051 return new SimpleBinaryExpression(binaryType, left, right, typeof(bool?));
1053 return new LogicalBinaryExpression(binaryType, left, right);
1056 throw Error.BinaryOperatorNotDefined(binaryType, left.Type, right.Type);
1061 #region Comparison Expressions
1065 /// Creates a <see cref="BinaryExpression"/> that represents a "greater than" numeric comparison.
1067 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1068 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1069 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.GreaterThan"/>
1070 /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
1071 public static BinaryExpression GreaterThan(Expression left, Expression right) {
1072 return GreaterThan(left, right, false, null);
1076 /// Creates a <see cref="BinaryExpression"/> that represents a "greater than" numeric comparison.
1078 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1079 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1080 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
1081 /// <param name="liftToNull">true to set IsLiftedToNull to true; false to set IsLiftedToNull to false.</param>
1082 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.GreaterThan"/>
1083 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, <see cref="P:BinaryExpression.IsLiftedToNull"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
1085 public static BinaryExpression GreaterThan(Expression left, Expression right, bool liftToNull, MethodInfo method) {
1086 RequiresCanRead(left, "left");
1087 RequiresCanRead(right, "right");
1088 if (method == null) {
1089 return GetComparisonOperator(ExpressionType.GreaterThan, "op_GreaterThan", left, right, liftToNull);
1091 return GetMethodBasedBinaryOperator(ExpressionType.GreaterThan, left, right, method, liftToNull);
1095 /// Creates a <see cref="BinaryExpression"/> that represents a "less than" numeric comparison.
1097 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1098 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1099 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.LessThan"/>
1100 /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
1102 public static BinaryExpression LessThan(Expression left, Expression right) {
1103 return LessThan(left, right, false, null);
1107 /// Creates a <see cref="BinaryExpression"/> that represents a "less than" numeric comparison.
1109 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1110 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1111 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
1112 /// <param name="liftToNull">true to set IsLiftedToNull to true; false to set IsLiftedToNull to false.</param>
1113 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.LessThan"/>
1114 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, <see cref="P:BinaryExpression.IsLiftedToNull"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
1116 public static BinaryExpression LessThan(Expression left, Expression right, bool liftToNull, MethodInfo method) {
1117 RequiresCanRead(left, "left");
1118 RequiresCanRead(right, "right");
1119 if (method == null) {
1120 return GetComparisonOperator(ExpressionType.LessThan, "op_LessThan", left, right, liftToNull);
1122 return GetMethodBasedBinaryOperator(ExpressionType.LessThan, left, right, method, liftToNull);
1127 /// Creates a <see cref="BinaryExpression"/> that represents a "greater than or equal" numeric comparison.
1129 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1130 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1131 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.GreaterThanOrEqual"/>
1132 /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
1133 public static BinaryExpression GreaterThanOrEqual(Expression left, Expression right) {
1134 return GreaterThanOrEqual(left, right, false, null);
1138 /// Creates a <see cref="BinaryExpression"/> that represents a "greater than or equal" numeric comparison.
1140 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1141 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1142 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
1143 /// <param name="liftToNull">true to set IsLiftedToNull to true; false to set IsLiftedToNull to false.</param>
1144 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.GreaterThanOrEqual"/>
1145 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, <see cref="P:BinaryExpression.IsLiftedToNull"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
1147 public static BinaryExpression GreaterThanOrEqual(Expression left, Expression right, bool liftToNull, MethodInfo method) {
1148 RequiresCanRead(left, "left");
1149 RequiresCanRead(right, "right");
1150 if (method == null) {
1151 return GetComparisonOperator(ExpressionType.GreaterThanOrEqual, "op_GreaterThanOrEqual", left, right, liftToNull);
1153 return GetMethodBasedBinaryOperator(ExpressionType.GreaterThanOrEqual, left, right, method, liftToNull);
1158 /// Creates a <see cref="BinaryExpression"/> that represents a "less than or equal" numeric comparison.
1160 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1161 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1162 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.LessThanOrEqual"/>
1163 /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
1164 public static BinaryExpression LessThanOrEqual(Expression left, Expression right) {
1165 return LessThanOrEqual(left, right, false, null);
1169 /// Creates a <see cref="BinaryExpression"/> that represents a "less than or equal" numeric comparison.
1171 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1172 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1173 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
1174 /// <param name="liftToNull">true to set IsLiftedToNull to true; false to set IsLiftedToNull to false.</param>
1175 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.LessThanOrEqual"/>
1176 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, <see cref="P:BinaryExpression.IsLiftedToNull"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
1178 public static BinaryExpression LessThanOrEqual(Expression left, Expression right, bool liftToNull, MethodInfo method) {
1179 RequiresCanRead(left, "left");
1180 RequiresCanRead(right, "right");
1181 if (method == null) {
1182 return GetComparisonOperator(ExpressionType.LessThanOrEqual, "op_LessThanOrEqual", left, right, liftToNull);
1184 return GetMethodBasedBinaryOperator(ExpressionType.LessThanOrEqual, left, right, method, liftToNull);
1188 private static BinaryExpression GetComparisonOperator(ExpressionType binaryType, string opName, Expression left, Expression right, bool liftToNull) {
1189 if (left.Type == right.Type && TypeUtils.IsNumeric(left.Type)) {
1190 if (TypeUtils.IsNullableType(left.Type) && liftToNull) {
1191 return new SimpleBinaryExpression(binaryType, left, right, typeof(bool?));
1193 return new LogicalBinaryExpression(binaryType, left, right);
1196 return GetUserDefinedBinaryOperatorOrThrow(binaryType, opName, left, right, liftToNull);
1201 #region Boolean Expressions
1205 /// Creates a <see cref="BinaryExpression"/> that represents a conditional AND operation that evaluates the second operand only if it has to.
1207 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1208 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1209 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.AndAlso"/>
1210 /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
1211 public static BinaryExpression AndAlso(Expression left, Expression right) {
1212 return AndAlso(left, right, null);
1216 /// Creates a <see cref="BinaryExpression"/> that represents a conditional AND operation that evaluates the second operand only if it has to.
1218 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1219 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1220 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
1221 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.AndAlso"/>
1222 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
1224 public static BinaryExpression AndAlso(Expression left, Expression right, MethodInfo method) {
1225 RequiresCanRead(left, "left");
1226 RequiresCanRead(right, "right");
1228 if (method == null) {
1229 if (left.Type == right.Type) {
1230 if (left.Type == typeof(bool)) {
1231 return new LogicalBinaryExpression(ExpressionType.AndAlso, left, right);
1232 } else if (left.Type == typeof(bool?)) {
1233 return new SimpleBinaryExpression(ExpressionType.AndAlso, left, right, left.Type);
1236 method = GetUserDefinedBinaryOperator(ExpressionType.AndAlso, left.Type, right.Type, "op_BitwiseAnd");
1237 if (method != null) {
1238 ValidateUserDefinedConditionalLogicOperator(ExpressionType.AndAlso, left.Type, right.Type, method);
1239 returnType = (TypeUtils.IsNullableType(left.Type) && TypeUtils.AreEquivalent(method.ReturnType, TypeUtils.GetNonNullableType(left.Type))) ? left.Type : method.ReturnType;
1240 return new MethodBinaryExpression(ExpressionType.AndAlso, left, right, returnType, method);
1242 throw Error.BinaryOperatorNotDefined(ExpressionType.AndAlso, left.Type, right.Type);
1244 ValidateUserDefinedConditionalLogicOperator(ExpressionType.AndAlso, left.Type, right.Type, method);
1245 returnType = (TypeUtils.IsNullableType(left.Type) && TypeUtils.AreEquivalent(method.ReturnType, TypeUtils.GetNonNullableType(left.Type))) ? left.Type : method.ReturnType;
1246 return new MethodBinaryExpression(ExpressionType.AndAlso, left, right, returnType, method);
1251 /// Creates a <see cref="BinaryExpression"/> that represents a conditional OR operation that evaluates the second operand only if it has to.
1253 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1254 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1255 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.OrElse"/>
1256 /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
1257 public static BinaryExpression OrElse(Expression left, Expression right) {
1258 return OrElse(left, right, null);
1262 /// Creates a <see cref="BinaryExpression"/> that represents a conditional OR operation that evaluates the second operand only if it has to.
1264 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1265 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1266 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
1267 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.OrElse"/>
1268 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
1270 public static BinaryExpression OrElse(Expression left, Expression right, MethodInfo method) {
1271 RequiresCanRead(left, "left");
1272 RequiresCanRead(right, "right");
1274 if (method == null) {
1275 if (left.Type == right.Type) {
1276 if (left.Type == typeof(bool)) {
1277 return new LogicalBinaryExpression(ExpressionType.OrElse, left, right);
1278 } else if (left.Type == typeof(bool?)) {
1279 return new SimpleBinaryExpression(ExpressionType.OrElse, left, right, left.Type);
1282 method = GetUserDefinedBinaryOperator(ExpressionType.OrElse, left.Type, right.Type, "op_BitwiseOr");
1283 if (method != null) {
1284 ValidateUserDefinedConditionalLogicOperator(ExpressionType.OrElse, left.Type, right.Type, method);
1285 returnType = (TypeUtils.IsNullableType(left.Type) && method.ReturnType == TypeUtils.GetNonNullableType(left.Type)) ? left.Type : method.ReturnType;
1286 return new MethodBinaryExpression(ExpressionType.OrElse, left, right, returnType, method);
1288 throw Error.BinaryOperatorNotDefined(ExpressionType.OrElse, left.Type, right.Type);
1290 ValidateUserDefinedConditionalLogicOperator(ExpressionType.OrElse, left.Type, right.Type, method);
1291 returnType = (TypeUtils.IsNullableType(left.Type) && method.ReturnType == TypeUtils.GetNonNullableType(left.Type)) ? left.Type : method.ReturnType;
1292 return new MethodBinaryExpression(ExpressionType.OrElse, left, right, returnType, method);
1297 #region Coalescing Expressions
1301 /// Creates a BinaryExpression that represents a coalescing operation.
1303 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1304 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1305 /// <returns>A BinaryExpression that has the NodeType property equal to Coalesce and the Left and Right properties set to the specified values.</returns>
1306 public static BinaryExpression Coalesce(Expression left, Expression right) {
1307 return Coalesce(left, right, null);
1312 /// Creates a BinaryExpression that represents a coalescing operation.
1314 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1315 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1316 /// <param name="conversion">A LambdaExpression to set the Conversion property equal to.</param>
1317 /// <returns>A BinaryExpression that has the NodeType property equal to Coalesce and the Left, Right and Conversion properties set to the specified values.
1319 public static BinaryExpression Coalesce(Expression left, Expression right, LambdaExpression conversion) {
1320 RequiresCanRead(left, "left");
1321 RequiresCanRead(right, "right");
1323 if (conversion == null) {
1324 Type resultType = ValidateCoalesceArgTypes(left.Type, right.Type);
1325 return new SimpleBinaryExpression(ExpressionType.Coalesce, left, right, resultType);
1328 if (left.Type.IsValueType && !TypeUtils.IsNullableType(left.Type)) {
1329 throw Error.CoalesceUsedOnNonNullType();
1332 Type delegateType = conversion.Type;
1333 Debug.Assert(typeof(System.MulticastDelegate).IsAssignableFrom(delegateType) && delegateType != typeof(System.MulticastDelegate));
1334 MethodInfo method = delegateType.GetMethod("Invoke");
1335 if (method.ReturnType == typeof(void)) {
1336 throw Error.UserDefinedOperatorMustNotBeVoid(conversion);
1338 ParameterInfo[] pms = method.GetParametersCached();
1339 Debug.Assert(pms.Length == conversion.Parameters.Count);
1340 if (pms.Length != 1) {
1341 throw Error.IncorrectNumberOfMethodCallArguments(conversion);
1343 // The return type must match exactly.
1344 // CONSIDER: We could weaken this restriction and
1345 // CONSIDER: say that the return type must be assignable to from
1346 // CONSIDER: the return type of the lambda.
1347 if (!TypeUtils.AreEquivalent(method.ReturnType, right.Type)) {
1348 throw Error.OperandTypesDoNotMatchParameters(ExpressionType.Coalesce, conversion.ToString());
1350 // The parameter of the conversion lambda must either be assignable
1351 // from the erased or unerased type of the left hand side.
1352 if (!ParameterIsAssignable(pms[0], TypeUtils.GetNonNullableType(left.Type)) &&
1353 !ParameterIsAssignable(pms[0], left.Type)) {
1354 throw Error.OperandTypesDoNotMatchParameters(ExpressionType.Coalesce, conversion.ToString());
1356 return new CoalesceConversionBinaryExpression(left, right, conversion);
1360 private static Type ValidateCoalesceArgTypes(Type left, Type right) {
1361 Type leftStripped = TypeUtils.GetNonNullableType(left);
1362 if (left.IsValueType && !TypeUtils.IsNullableType(left)) {
1363 throw Error.CoalesceUsedOnNonNullType();
1364 } else if (TypeUtils.IsNullableType(left) && TypeUtils.IsImplicitlyConvertible(right, leftStripped)) {
1365 return leftStripped;
1366 } else if (TypeUtils.IsImplicitlyConvertible(right, left)) {
1368 } else if (TypeUtils.IsImplicitlyConvertible(leftStripped, right)) {
1371 throw Error.ArgumentTypesMustMatch();
1379 #region Arithmetic Expressions
1383 /// Creates a <see cref="BinaryExpression"/> that represents an arithmetic addition operation that does not have overflow checking.
1385 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1386 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1387 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.Add"/>
1388 /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
1389 public static BinaryExpression Add(Expression left, Expression right) {
1390 return Add(left, right, null);
1394 /// Creates a <see cref="BinaryExpression"/> that represents an arithmetic addition operation that does not have overflow checking.
1396 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1397 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1398 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
1399 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.Add"/>
1400 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
1402 public static BinaryExpression Add(Expression left, Expression right, MethodInfo method) {
1403 RequiresCanRead(left, "left");
1404 RequiresCanRead(right, "right");
1405 if (method == null) {
1406 if (left.Type == right.Type && TypeUtils.IsArithmetic(left.Type)) {
1407 return new SimpleBinaryExpression(ExpressionType.Add, left, right, left.Type);
1409 return GetUserDefinedBinaryOperatorOrThrow(ExpressionType.Add, "op_Addition", left, right, true);
1411 return GetMethodBasedBinaryOperator(ExpressionType.Add, left, right, method, true);
1416 /// Creates a <see cref="BinaryExpression"/> that represents an addition assignment operation that does not have overflow checking.
1418 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1419 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1420 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.AddAssign"/>
1421 /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
1422 public static BinaryExpression AddAssign(Expression left, Expression right) {
1423 return AddAssign(left, right, null, null);
1427 /// Creates a <see cref="BinaryExpression"/> that represents an addition assignment operation that does not have overflow checking.
1429 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1430 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1431 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
1432 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.AddAssign"/>
1433 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
1435 public static BinaryExpression AddAssign(Expression left, Expression right, MethodInfo method) {
1436 return AddAssign(left, right, method, null);
1440 /// Creates a <see cref="BinaryExpression"/> that represents an addition assignment operation that does not have overflow checking.
1442 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1443 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1444 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
1445 /// <param name="conversion">A <see cref="LambdaExpression"/> to set the <see cref="P:BinaryExpression.Conversion"/> property equal to.</param>
1446 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.AddAssign"/>
1447 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, <see cref="P:BinaryExpression.Method"/>,
1448 /// and <see cref="P:BinaryExpression.Conversion"/> properties set to the specified values.
1451 public static BinaryExpression AddAssign(Expression left, Expression right, MethodInfo method, LambdaExpression conversion) {
1452 RequiresCanRead(left, "left");
1453 RequiresCanWrite(left, "left");
1454 RequiresCanRead(right, "right");
1455 if (method == null) {
1456 if (left.Type == right.Type && TypeUtils.IsArithmetic(left.Type)) {
1457 // conversion is not supported for binary ops on arithmetic types without operator overloading
1458 if (conversion != null) {
1459 throw Error.ConversionIsNotSupportedForArithmeticTypes();
1461 return new SimpleBinaryExpression(ExpressionType.AddAssign, left, right, left.Type);
1463 return GetUserDefinedAssignOperatorOrThrow(ExpressionType.AddAssign, "op_Addition", left, right, conversion, true);
1465 return GetMethodBasedAssignOperator(ExpressionType.AddAssign, left, right, method, conversion, true);
1468 private static void ValidateOpAssignConversionLambda(LambdaExpression conversion, Expression left, MethodInfo method, ExpressionType nodeType) {
1469 Type delegateType = conversion.Type;
1470 Debug.Assert(typeof(System.MulticastDelegate).IsAssignableFrom(delegateType) && delegateType != typeof(System.MulticastDelegate));
1471 MethodInfo mi = delegateType.GetMethod("Invoke");
1472 ParameterInfo[] pms = mi.GetParametersCached();
1473 Debug.Assert(pms.Length == conversion.Parameters.Count);
1474 if (pms.Length != 1) {
1475 throw Error.IncorrectNumberOfMethodCallArguments(conversion);
1477 if (!TypeUtils.AreEquivalent(mi.ReturnType, left.Type)) {
1478 throw Error.OperandTypesDoNotMatchParameters(nodeType, conversion.ToString());
1480 if (method != null) {
1481 // The parameter type of conversion lambda must be the same as the return type of the overload method
1482 if (!TypeUtils.AreEquivalent(pms[0].ParameterType, method.ReturnType)) {
1483 throw Error.OverloadOperatorTypeDoesNotMatchConversionType(nodeType, conversion.ToString());
1490 /// Creates a <see cref="BinaryExpression"/> that represents an addition assignment operation that has overflow checking.
1492 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1493 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1494 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to
1495 /// <see cref="F:ExpressionType.AddAssignChecked"/> and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/>
1496 /// properties set to the specified values.
1498 public static BinaryExpression AddAssignChecked(Expression left, Expression right) {
1499 return AddAssignChecked(left, right, null);
1503 /// Creates a <see cref="BinaryExpression"/> that represents an addition assignment operation that has overflow checking.
1505 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1506 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1507 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
1508 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.AddAssignChecked"/>
1509 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
1511 public static BinaryExpression AddAssignChecked(Expression left, Expression right, MethodInfo method) {
1512 return AddAssignChecked(left, right, method, null);
1516 /// Creates a <see cref="BinaryExpression"/> that represents an addition assignment operation that has overflow checking.
1518 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1519 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1520 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
1521 /// <param name="conversion">A <see cref="LambdaExpression"/> to set the <see cref="P:BinaryExpression.Conversion"/> property equal to.</param>
1522 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.AddAssignChecked"/>
1523 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, <see cref="P:BinaryExpression.Method"/>,
1524 /// and <see cref="P:BinaryExpression.Conversion"/> properties set to the specified values.
1526 public static BinaryExpression AddAssignChecked(Expression left, Expression right, MethodInfo method, LambdaExpression conversion) {
1527 RequiresCanRead(left, "left");
1528 RequiresCanWrite(left, "left");
1529 RequiresCanRead(right, "right");
1531 if (method == null) {
1532 if (left.Type == right.Type && TypeUtils.IsArithmetic(left.Type)) {
1533 // conversion is not supported for binary ops on arithmetic types without operator overloading
1534 if (conversion != null) {
1535 throw Error.ConversionIsNotSupportedForArithmeticTypes();
1537 return new SimpleBinaryExpression(ExpressionType.AddAssignChecked, left, right, left.Type);
1539 return GetUserDefinedAssignOperatorOrThrow(ExpressionType.AddAssignChecked, "op_Addition", left, right, conversion, true);
1541 return GetMethodBasedAssignOperator(ExpressionType.AddAssignChecked, left, right, method, conversion, true);
1546 /// Creates a <see cref="BinaryExpression"/> that represents an arithmetic addition operation that has overflow checking.
1548 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1549 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1550 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.AddChecked"/>
1551 /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
1552 public static BinaryExpression AddChecked(Expression left, Expression right) {
1553 return AddChecked(left, right, null);
1557 /// Creates a <see cref="BinaryExpression"/> that represents an arithmetic addition operation that has overflow checking.
1559 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1560 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1561 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
1562 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.AddChecked"/>
1563 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
1565 public static BinaryExpression AddChecked(Expression left, Expression right, MethodInfo method) {
1566 RequiresCanRead(left, "left");
1567 RequiresCanRead(right, "right");
1568 if (method == null) {
1569 if (left.Type == right.Type && TypeUtils.IsArithmetic(left.Type)) {
1570 return new SimpleBinaryExpression(ExpressionType.AddChecked, left, right, left.Type);
1572 return GetUserDefinedBinaryOperatorOrThrow(ExpressionType.AddChecked, "op_Addition", left, right, false);
1574 return GetMethodBasedBinaryOperator(ExpressionType.AddChecked, left, right, method, true);
1579 /// Creates a <see cref="BinaryExpression"/> that represents an arithmetic subtraction operation that does not have overflow checking.
1581 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1582 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1583 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.Subtract"/>
1584 /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
1585 public static BinaryExpression Subtract(Expression left, Expression right) {
1586 return Subtract(left, right, null);
1590 /// Creates a <see cref="BinaryExpression"/> that represents an arithmetic subtraction operation that does not have overflow checking.
1592 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1593 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1594 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
1595 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.Subtract"/>
1596 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
1598 public static BinaryExpression Subtract(Expression left, Expression right, MethodInfo method) {
1599 RequiresCanRead(left, "left");
1600 RequiresCanRead(right, "right");
1601 if (method == null) {
1602 if (left.Type == right.Type && TypeUtils.IsArithmetic(left.Type)) {
1603 return new SimpleBinaryExpression(ExpressionType.Subtract, left, right, left.Type);
1605 return GetUserDefinedBinaryOperatorOrThrow(ExpressionType.Subtract, "op_Subtraction", left, right, true);
1607 return GetMethodBasedBinaryOperator(ExpressionType.Subtract, left, right, method, true);
1612 /// Creates a <see cref="BinaryExpression"/> that represents a subtraction assignment operation that does not have overflow checking.
1614 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1615 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1616 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.SubtractAssign"/>
1617 /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
1618 public static BinaryExpression SubtractAssign(Expression left, Expression right) {
1619 return SubtractAssign(left, right, null, null);
1623 /// Creates a <see cref="BinaryExpression"/> that represents a subtraction assignment operation that does not have overflow checking.
1625 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1626 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1627 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
1628 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.SubtractAssign"/>
1629 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
1631 public static BinaryExpression SubtractAssign(Expression left, Expression right, MethodInfo method) {
1632 return SubtractAssign(left, right, method, null);
1636 /// Creates a <see cref="BinaryExpression"/> that represents a subtraction assignment operation that does not have overflow checking.
1638 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1639 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1640 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
1641 /// <param name="conversion">A <see cref="LambdaExpression"/> to set the <see cref="P:BinaryExpression.Conversion"/> property equal to.</param>
1642 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.SubtractAssign"/>
1643 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, <see cref="P:BinaryExpression.Method"/>,
1644 /// and <see cref="P:BinaryExpression.Conversion"/> properties set to the specified values.
1646 public static BinaryExpression SubtractAssign(Expression left, Expression right, MethodInfo method, LambdaExpression conversion) {
1647 RequiresCanRead(left, "left");
1648 RequiresCanWrite(left, "left");
1649 RequiresCanRead(right, "right");
1650 if (method == null) {
1651 if (left.Type == right.Type && TypeUtils.IsArithmetic(left.Type)) {
1652 // conversion is not supported for binary ops on arithmetic types without operator overloading
1653 if (conversion != null) {
1654 throw Error.ConversionIsNotSupportedForArithmeticTypes();
1656 return new SimpleBinaryExpression(ExpressionType.SubtractAssign, left, right, left.Type);
1658 return GetUserDefinedAssignOperatorOrThrow(ExpressionType.SubtractAssign, "op_Subtraction", left, right, conversion, true);
1660 return GetMethodBasedAssignOperator(ExpressionType.SubtractAssign, left, right, method, conversion, true);
1665 /// Creates a <see cref="BinaryExpression"/> that represents a subtraction assignment operation that has overflow checking.
1667 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1668 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1669 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.SubtractAssignChecked"/>
1670 /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
1671 public static BinaryExpression SubtractAssignChecked(Expression left, Expression right) {
1672 return SubtractAssignChecked(left, right, null);
1676 /// Creates a <see cref="BinaryExpression"/> that represents a subtraction assignment operation that has overflow checking.
1678 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1679 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1680 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
1681 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.SubtractAssignChecked"/>
1682 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
1684 public static BinaryExpression SubtractAssignChecked(Expression left, Expression right, MethodInfo method) {
1685 return SubtractAssignChecked(left, right, method, null);
1689 /// Creates a <see cref="BinaryExpression"/> that represents a subtraction assignment operation that has overflow checking.
1691 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1692 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1693 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
1694 /// <param name="conversion">A <see cref="LambdaExpression"/> to set the <see cref="P:BinaryExpression.Conversion"/> property equal to.</param>
1695 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.SubtractAssignChecked"/>
1696 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, <see cref="P:BinaryExpression.Method"/>,
1697 /// and <see cref="P:BinaryExpression.Conversion"/> properties set to the specified values.
1699 public static BinaryExpression SubtractAssignChecked(Expression left, Expression right, MethodInfo method, LambdaExpression conversion) {
1700 RequiresCanRead(left, "left");
1701 RequiresCanWrite(left, "left");
1702 RequiresCanRead(right, "right");
1703 if (method == null) {
1704 if (left.Type == right.Type && TypeUtils.IsArithmetic(left.Type)) {
1705 // conversion is not supported for binary ops on arithmetic types without operator overloading
1706 if (conversion != null) {
1707 throw Error.ConversionIsNotSupportedForArithmeticTypes();
1709 return new SimpleBinaryExpression(ExpressionType.SubtractAssignChecked, left, right, left.Type);
1711 return GetUserDefinedAssignOperatorOrThrow(ExpressionType.SubtractAssignChecked, "op_Subtraction", left, right, conversion, true);
1713 return GetMethodBasedAssignOperator(ExpressionType.SubtractAssignChecked, left, right, method, conversion, true);
1718 /// Creates a <see cref="BinaryExpression"/> that represents an arithmetic subtraction operation that has overflow checking.
1720 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1721 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1722 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.SubtractChecked"/>
1723 /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
1724 public static BinaryExpression SubtractChecked(Expression left, Expression right) {
1725 return SubtractChecked(left, right, null);
1729 /// Creates a <see cref="BinaryExpression"/> that represents an arithmetic subtraction operation that has overflow checking.
1731 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1732 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1733 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
1734 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.SubtractChecked"/>
1735 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
1737 public static BinaryExpression SubtractChecked(Expression left, Expression right, MethodInfo method) {
1738 RequiresCanRead(left, "left");
1739 RequiresCanRead(right, "right");
1740 if (method == null) {
1741 if (left.Type == right.Type && TypeUtils.IsArithmetic(left.Type)) {
1742 return new SimpleBinaryExpression(ExpressionType.SubtractChecked, left, right, left.Type);
1744 return GetUserDefinedBinaryOperatorOrThrow(ExpressionType.SubtractChecked, "op_Subtraction", left, right, true);
1746 return GetMethodBasedBinaryOperator(ExpressionType.SubtractChecked, left, right, method, true);
1751 /// Creates a <see cref="BinaryExpression"/> that represents an arithmetic division operation.
1753 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1754 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1755 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.Divide"/>
1756 /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
1757 public static BinaryExpression Divide(Expression left, Expression right) {
1758 return Divide(left, right, null);
1762 /// Creates a <see cref="BinaryExpression"/> that represents an arithmetic division operation.
1764 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1765 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1766 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
1767 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.Divide"/>
1768 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
1770 public static BinaryExpression Divide(Expression left, Expression right, MethodInfo method) {
1771 RequiresCanRead(left, "left");
1772 RequiresCanRead(right, "right");
1773 if (method == null) {
1774 if (left.Type == right.Type && TypeUtils.IsArithmetic(left.Type)) {
1775 return new SimpleBinaryExpression(ExpressionType.Divide, left, right, left.Type);
1777 return GetUserDefinedBinaryOperatorOrThrow(ExpressionType.Divide, "op_Division", left, right, true);
1779 return GetMethodBasedBinaryOperator(ExpressionType.Divide, left, right, method, true);
1784 /// Creates a <see cref="BinaryExpression"/> that represents a division assignment operation that does not have overflow checking.
1786 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1787 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1788 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.DivideAssign"/>
1789 /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
1790 public static BinaryExpression DivideAssign(Expression left, Expression right) {
1791 return DivideAssign(left, right, null, null);
1795 /// Creates a <see cref="BinaryExpression"/> that represents a division assignment operation that does not have overflow checking.
1797 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1798 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1799 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
1800 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.DivideAssign"/>
1801 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
1803 public static BinaryExpression DivideAssign(Expression left, Expression right, MethodInfo method) {
1804 return DivideAssign(left, right, method, null);
1808 /// Creates a <see cref="BinaryExpression"/> that represents a division assignment operation that does not have overflow checking.
1810 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1811 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1812 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
1813 /// <param name="conversion">A <see cref="LambdaExpression"/> to set the <see cref="P:BinaryExpression.Conversion"/> property equal to.</param>
1814 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.DivideAssign"/>
1815 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, <see cref="P:BinaryExpression.Method"/>,
1816 /// and <see cref="P:BinaryExpression.Conversion"/> properties set to the specified values.
1818 public static BinaryExpression DivideAssign(Expression left, Expression right, MethodInfo method, LambdaExpression conversion) {
1819 RequiresCanRead(left, "left");
1820 RequiresCanWrite(left, "left");
1821 RequiresCanRead(right, "right");
1822 if (method == null) {
1823 if (left.Type == right.Type && TypeUtils.IsArithmetic(left.Type)) {
1824 // conversion is not supported for binary ops on arithmetic types without operator overloading
1825 if (conversion != null) {
1826 throw Error.ConversionIsNotSupportedForArithmeticTypes();
1828 return new SimpleBinaryExpression(ExpressionType.DivideAssign, left, right, left.Type);
1830 return GetUserDefinedAssignOperatorOrThrow(ExpressionType.DivideAssign, "op_Division", left, right, conversion, true);
1832 return GetMethodBasedAssignOperator(ExpressionType.DivideAssign, left, right, method, conversion, true);
1837 /// Creates a <see cref="BinaryExpression"/> that represents an arithmetic remainder operation.
1839 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1840 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1841 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.Modulo"/>
1842 /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
1843 public static BinaryExpression Modulo(Expression left, Expression right) {
1844 return Modulo(left, right, null);
1848 /// Creates a <see cref="BinaryExpression"/> that represents an arithmetic remainder operation.
1850 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1851 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1852 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
1853 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.Modulo"/>
1854 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
1856 public static BinaryExpression Modulo(Expression left, Expression right, MethodInfo method) {
1857 RequiresCanRead(left, "left");
1858 RequiresCanRead(right, "right");
1859 if (method == null) {
1860 if (left.Type == right.Type && TypeUtils.IsArithmetic(left.Type)) {
1861 return new SimpleBinaryExpression(ExpressionType.Modulo, left, right, left.Type);
1863 return GetUserDefinedBinaryOperatorOrThrow(ExpressionType.Modulo, "op_Modulus", left, right, true);
1865 return GetMethodBasedBinaryOperator(ExpressionType.Modulo, left, right, method, true);
1870 /// Creates a <see cref="BinaryExpression"/> that represents a remainder assignment operation.
1872 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1873 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1874 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.ModuloAssign"/>
1875 /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
1876 public static BinaryExpression ModuloAssign(Expression left, Expression right) {
1877 return ModuloAssign(left, right, null, null);
1881 /// Creates a <see cref="BinaryExpression"/> that represents a remainder assignment operation.
1883 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1884 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1885 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
1886 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.ModuloAssign"/>
1887 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
1889 public static BinaryExpression ModuloAssign(Expression left, Expression right, MethodInfo method) {
1890 return ModuloAssign(left, right, method, null);
1894 /// Creates a <see cref="BinaryExpression"/> that represents a remainder assignment operation.
1896 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1897 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1898 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
1899 /// <param name="conversion">A <see cref="LambdaExpression"/> to set the <see cref="P:BinaryExpression.Conversion"/> property equal to.</param>
1900 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.ModuloAssign"/>
1901 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, <see cref="P:BinaryExpression.Method"/>,
1902 /// and <see cref="P:BinaryExpression.Conversion"/> properties set to the specified values.
1904 public static BinaryExpression ModuloAssign(Expression left, Expression right, MethodInfo method, LambdaExpression conversion) {
1905 RequiresCanRead(left, "left");
1906 RequiresCanWrite(left, "left");
1907 RequiresCanRead(right, "right");
1908 if (method == null) {
1909 if (left.Type == right.Type && TypeUtils.IsArithmetic(left.Type)) {
1910 // conversion is not supported for binary ops on arithmetic types without operator overloading
1911 if (conversion != null) {
1912 throw Error.ConversionIsNotSupportedForArithmeticTypes();
1914 return new SimpleBinaryExpression(ExpressionType.ModuloAssign, left, right, left.Type);
1916 return GetUserDefinedAssignOperatorOrThrow(ExpressionType.ModuloAssign, "op_Modulus", left, right, conversion, true);
1918 return GetMethodBasedAssignOperator(ExpressionType.ModuloAssign, left, right, method, conversion, true);
1923 /// Creates a <see cref="BinaryExpression"/> that represents an arithmetic multiplication operation that does not have overflow checking.
1925 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1926 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1927 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.Multiply"/>
1928 /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
1929 public static BinaryExpression Multiply(Expression left, Expression right) {
1930 return Multiply(left, right, null);
1934 /// Creates a <see cref="BinaryExpression"/> that represents an arithmetic multiplication operation that does not have overflow checking.
1936 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1937 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1938 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
1939 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.Multiply"/>
1940 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
1942 public static BinaryExpression Multiply(Expression left, Expression right, MethodInfo method) {
1943 RequiresCanRead(left, "left");
1944 RequiresCanRead(right, "right");
1945 if (method == null) {
1946 if (left.Type == right.Type && TypeUtils.IsArithmetic(left.Type)) {
1947 return new SimpleBinaryExpression(ExpressionType.Multiply, left, right, left.Type);
1949 return GetUserDefinedBinaryOperatorOrThrow(ExpressionType.Multiply, "op_Multiply", left, right, true);
1951 return GetMethodBasedBinaryOperator(ExpressionType.Multiply, left, right, method, true);
1956 /// Creates a <see cref="BinaryExpression"/> that represents a multiplication assignment operation that does not have overflow checking.
1958 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1959 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1960 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.MultiplyAssign"/>
1961 /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
1962 public static BinaryExpression MultiplyAssign(Expression left, Expression right) {
1963 return MultiplyAssign(left, right, null, null);
1967 /// Creates a <see cref="BinaryExpression"/> that represents a multiplication assignment operation that does not have overflow checking.
1969 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1970 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1971 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
1972 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.MultiplyAssign"/>
1973 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
1975 public static BinaryExpression MultiplyAssign(Expression left, Expression right, MethodInfo method) {
1976 return MultiplyAssign(left, right, method, null);
1980 /// Creates a <see cref="BinaryExpression"/> that represents a multiplication assignment operation that does not have overflow checking.
1982 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1983 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1984 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
1985 /// <param name="conversion">A <see cref="LambdaExpression"/> to set the <see cref="P:BinaryExpression.Conversion"/> property equal to.</param>
1986 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.MultiplyAssign"/>
1987 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, <see cref="P:BinaryExpression.Method"/>,
1988 /// and <see cref="P:BinaryExpression.Conversion"/> properties set to the specified values.
1990 public static BinaryExpression MultiplyAssign(Expression left, Expression right, MethodInfo method, LambdaExpression conversion) {
1991 RequiresCanRead(left, "left");
1992 RequiresCanWrite(left, "left");
1993 RequiresCanRead(right, "right");
1994 if (method == null) {
1995 if (left.Type == right.Type && TypeUtils.IsArithmetic(left.Type)) {
1996 // conversion is not supported for binary ops on arithmetic types without operator overloading
1997 if (conversion != null) {
1998 throw Error.ConversionIsNotSupportedForArithmeticTypes();
2000 return new SimpleBinaryExpression(ExpressionType.MultiplyAssign, left, right, left.Type);
2002 return GetUserDefinedAssignOperatorOrThrow(ExpressionType.MultiplyAssign, "op_Multiply", left, right, conversion, true);
2004 return GetMethodBasedAssignOperator(ExpressionType.MultiplyAssign, left, right, method, conversion, true);
2009 /// Creates a <see cref="BinaryExpression"/> that represents a multiplication assignment operation that has overflow checking.
2011 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
2012 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
2013 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.MultiplyAssignChecked"/>
2014 /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
2015 public static BinaryExpression MultiplyAssignChecked(Expression left, Expression right) {
2016 return MultiplyAssignChecked(left, right, null);
2020 /// Creates a <see cref="BinaryExpression"/> that represents a multiplication assignment operation that has overflow checking.
2022 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
2023 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
2024 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
2025 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.MultiplyAssignChecked"/>
2026 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
2028 public static BinaryExpression MultiplyAssignChecked(Expression left, Expression right, MethodInfo method) {
2029 return MultiplyAssignChecked(left, right, method, null);
2033 /// Creates a <see cref="BinaryExpression"/> that represents a multiplication assignment operation that has overflow checking.
2035 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
2036 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
2037 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
2038 /// <param name="conversion">A <see cref="LambdaExpression"/> to set the <see cref="P:BinaryExpression.Conversion"/> property equal to.</param>
2039 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.MultiplyAssignChecked"/>
2040 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, <see cref="P:BinaryExpression.Method"/>,
2041 /// and <see cref="P:BinaryExpression.Conversion"/> properties set to the specified values.
2043 public static BinaryExpression MultiplyAssignChecked(Expression left, Expression right, MethodInfo method, LambdaExpression conversion) {
2044 RequiresCanRead(left, "left");
2045 RequiresCanWrite(left, "left");
2046 RequiresCanRead(right, "right");
2047 if (method == null) {
2048 if (left.Type == right.Type && TypeUtils.IsArithmetic(left.Type)) {
2049 // conversion is not supported for binary ops on arithmetic types without operator overloading
2050 if (conversion != null) {
2051 throw Error.ConversionIsNotSupportedForArithmeticTypes();
2053 return new SimpleBinaryExpression(ExpressionType.MultiplyAssignChecked, left, right, left.Type);
2055 return GetUserDefinedAssignOperatorOrThrow(ExpressionType.MultiplyAssignChecked, "op_Multiply", left, right, conversion, true);
2057 return GetMethodBasedAssignOperator(ExpressionType.MultiplyAssignChecked, left, right, method, conversion, true);
2062 /// Creates a <see cref="BinaryExpression"/> that represents an arithmetic multiplication operation that has overflow checking.
2064 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
2065 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
2066 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.MultiplyChecked"/>
2067 /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
2068 public static BinaryExpression MultiplyChecked(Expression left, Expression right) {
2069 return MultiplyChecked(left, right, null);
2073 /// Creates a <see cref="BinaryExpression"/> that represents an arithmetic multiplication operation that has overflow checking.
2075 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
2076 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
2077 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
2078 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.MultiplyChecked"/>
2079 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
2081 public static BinaryExpression MultiplyChecked(Expression left, Expression right, MethodInfo method) {
2082 RequiresCanRead(left, "left");
2083 RequiresCanRead(right, "right");
2084 if (method == null) {
2085 if (left.Type == right.Type && TypeUtils.IsArithmetic(left.Type)) {
2086 return new SimpleBinaryExpression(ExpressionType.MultiplyChecked, left, right, left.Type);
2088 return GetUserDefinedBinaryOperatorOrThrow(ExpressionType.MultiplyChecked, "op_Multiply", left, right, true);
2090 return GetMethodBasedBinaryOperator(ExpressionType.MultiplyChecked, left, right, method, true);
2093 private static bool IsSimpleShift(Type left, Type right) {
2094 return TypeUtils.IsInteger(left)
2095 && TypeUtils.GetNonNullableType(right) == typeof(int);
2098 private static Type GetResultTypeOfShift(Type left, Type right) {
2099 if (!left.IsNullableType() && right.IsNullableType()) {
2100 // lift the result type to Nullable<T>
2101 return typeof(Nullable<>).MakeGenericType(left);
2108 /// Creates a <see cref="BinaryExpression"/> that represents an bitwise left-shift operation.
2110 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
2111 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
2112 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.LeftShift"/>
2113 /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
2114 public static BinaryExpression LeftShift(Expression left, Expression right) {
2115 return LeftShift(left, right, null);
2119 /// Creates a <see cref="BinaryExpression"/> that represents an bitwise left-shift operation.
2121 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
2122 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
2123 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
2124 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.LeftShift"/>
2125 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
2127 public static BinaryExpression LeftShift(Expression left, Expression right, MethodInfo method) {
2128 RequiresCanRead(left, "left");
2129 RequiresCanRead(right, "right");
2130 if (method == null) {
2131 if (IsSimpleShift(left.Type, right.Type)) {
2132 Type resultType = GetResultTypeOfShift(left.Type, right.Type);
2133 return new SimpleBinaryExpression(ExpressionType.LeftShift, left, right, resultType);
2135 return GetUserDefinedBinaryOperatorOrThrow(ExpressionType.LeftShift, "op_LeftShift", left, right, true);
2137 return GetMethodBasedBinaryOperator(ExpressionType.LeftShift, left, right, method, true);
2142 /// Creates a <see cref="BinaryExpression"/> that represents a bitwise left-shift assignment operation.
2144 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
2145 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
2146 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.LeftShiftAssign"/>
2147 /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
2148 public static BinaryExpression LeftShiftAssign(Expression left, Expression right) {
2149 return LeftShiftAssign(left, right, null, null);
2153 /// Creates a <see cref="BinaryExpression"/> that represents a bitwise left-shift assignment operation.
2155 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
2156 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
2157 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
2158 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.LeftShiftAssign"/>
2159 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
2161 public static BinaryExpression LeftShiftAssign(Expression left, Expression right, MethodInfo method) {
2162 return LeftShiftAssign(left, right, method, null);
2166 /// Creates a <see cref="BinaryExpression"/> that represents a bitwise left-shift assignment operation.
2168 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
2169 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
2170 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
2171 /// <param name="conversion">A <see cref="LambdaExpression"/> to set the <see cref="P:BinaryExpression.Conversion"/> property equal to.</param>
2172 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.LeftShiftAssign"/>
2173 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, <see cref="P:BinaryExpression.Method"/>,
2174 /// and <see cref="P:BinaryExpression.Conversion"/> properties set to the specified values.
2176 public static BinaryExpression LeftShiftAssign(Expression left, Expression right, MethodInfo method, LambdaExpression conversion) {
2177 RequiresCanRead(left, "left");
2178 RequiresCanWrite(left, "left");
2179 RequiresCanRead(right, "right");
2180 if (method == null) {
2181 if (IsSimpleShift(left.Type, right.Type)) {
2182 // conversion is not supported for binary ops on arithmetic types without operator overloading
2183 if (conversion != null) {
2184 throw Error.ConversionIsNotSupportedForArithmeticTypes();
2186 Type resultType = GetResultTypeOfShift(left.Type, right.Type);
2187 return new SimpleBinaryExpression(ExpressionType.LeftShiftAssign, left, right, resultType);
2189 return GetUserDefinedAssignOperatorOrThrow(ExpressionType.LeftShiftAssign, "op_LeftShift", left, right, conversion, true);
2191 return GetMethodBasedAssignOperator(ExpressionType.LeftShiftAssign, left, right, method, conversion, true);
2196 /// Creates a <see cref="BinaryExpression"/> that represents an bitwise right-shift operation.
2198 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
2199 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
2200 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.RightShift"/>
2201 /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
2202 public static BinaryExpression RightShift(Expression left, Expression right) {
2203 return RightShift(left, right, null);
2207 /// Creates a <see cref="BinaryExpression"/> that represents an bitwise right-shift operation.
2209 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
2210 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
2211 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
2212 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.RightShift"/>
2213 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
2215 public static BinaryExpression RightShift(Expression left, Expression right, MethodInfo method) {
2216 RequiresCanRead(left, "left");
2217 RequiresCanRead(right, "right");
2218 if (method == null) {
2219 if (IsSimpleShift(left.Type, right.Type)) {
2220 Type resultType = GetResultTypeOfShift(left.Type, right.Type);
2221 return new SimpleBinaryExpression(ExpressionType.RightShift, left, right, resultType);
2223 return GetUserDefinedBinaryOperatorOrThrow(ExpressionType.RightShift, "op_RightShift", left, right, true);
2225 return GetMethodBasedBinaryOperator(ExpressionType.RightShift, left, right, method, true);
2230 /// Creates a <see cref="BinaryExpression"/> that represents a bitwise right-shift assignment operation.
2232 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
2233 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
2234 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.RightShiftAssign"/>
2235 /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
2236 public static BinaryExpression RightShiftAssign(Expression left, Expression right) {
2237 return RightShiftAssign(left, right, null, null);
2241 /// Creates a <see cref="BinaryExpression"/> that represents a bitwise right-shift assignment operation.
2243 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
2244 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
2245 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
2246 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.RightShiftAssign"/>
2247 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
2249 public static BinaryExpression RightShiftAssign(Expression left, Expression right, MethodInfo method) {
2250 return RightShiftAssign(left, right, method, null);
2254 /// Creates a <see cref="BinaryExpression"/> that represents a bitwise right-shift assignment operation.
2256 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
2257 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
2258 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
2259 /// <param name="conversion">A <see cref="LambdaExpression"/> to set the <see cref="P:BinaryExpression.Conversion"/> property equal to.</param>
2260 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.RightShiftAssign"/>
2261 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, <see cref="P:BinaryExpression.Method"/>,
2262 /// and <see cref="P:BinaryExpression.Conversion"/> properties set to the specified values.
2264 public static BinaryExpression RightShiftAssign(Expression left, Expression right, MethodInfo method, LambdaExpression conversion) {
2265 RequiresCanRead(left, "left");
2266 RequiresCanWrite(left, "left");
2267 RequiresCanRead(right, "right");
2268 if (method == null) {
2269 if (IsSimpleShift(left.Type, right.Type)) {
2270 // conversion is not supported for binary ops on arithmetic types without operator overloading
2271 if (conversion != null) {
2272 throw Error.ConversionIsNotSupportedForArithmeticTypes();
2274 Type resultType = GetResultTypeOfShift(left.Type, right.Type);
2275 return new SimpleBinaryExpression(ExpressionType.RightShiftAssign, left, right, resultType);
2277 return GetUserDefinedAssignOperatorOrThrow(ExpressionType.RightShiftAssign, "op_RightShift", left, right, conversion, true);
2279 return GetMethodBasedAssignOperator(ExpressionType.RightShiftAssign, left, right, method, conversion, true);
2284 /// Creates a <see cref="BinaryExpression"/> that represents an bitwise AND operation.
2286 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
2287 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
2288 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.And"/>
2289 /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
2290 public static BinaryExpression And(Expression left, Expression right) {
2291 return And(left, right, null);
2295 /// Creates a <see cref="BinaryExpression"/> that represents an bitwise AND operation.
2297 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
2298 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
2299 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
2300 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.And"/>
2301 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
2303 public static BinaryExpression And(Expression left, Expression right, MethodInfo method) {
2304 RequiresCanRead(left, "left");
2305 RequiresCanRead(right, "right");
2306 if (method == null) {
2307 if (left.Type == right.Type && TypeUtils.IsIntegerOrBool(left.Type)) {
2308 return new SimpleBinaryExpression(ExpressionType.And, left, right, left.Type);
2310 return GetUserDefinedBinaryOperatorOrThrow(ExpressionType.And, "op_BitwiseAnd", left, right, true);
2312 return GetMethodBasedBinaryOperator(ExpressionType.And, left, right, method, true);
2317 /// Creates a <see cref="BinaryExpression"/> that represents a bitwise AND assignment operation.
2319 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
2320 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
2321 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.AndAssign"/>
2322 /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
2323 public static BinaryExpression AndAssign(Expression left, Expression right) {
2324 return AndAssign(left, right, null, null);
2328 /// Creates a <see cref="BinaryExpression"/> that represents a bitwise AND assignment operation.
2330 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
2331 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
2332 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
2333 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.AndAssign"/>
2334 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
2336 public static BinaryExpression AndAssign(Expression left, Expression right, MethodInfo method) {
2337 return AndAssign(left, right, method, null);
2341 /// Creates a <see cref="BinaryExpression"/> that represents a bitwise AND assignment operation.
2343 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
2344 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
2345 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
2346 /// <param name="conversion">A <see cref="LambdaExpression"/> to set the <see cref="P:BinaryExpression.Conversion"/> property equal to.</param>
2347 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.AndAssign"/>
2348 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, <see cref="P:BinaryExpression.Method"/>,
2349 /// and <see cref="P:BinaryExpression.Conversion"/> properties set to the specified values.
2351 public static BinaryExpression AndAssign(Expression left, Expression right, MethodInfo method, LambdaExpression conversion) {
2352 RequiresCanRead(left, "left");
2353 RequiresCanWrite(left, "left");
2354 RequiresCanRead(right, "right");
2355 if (method == null) {
2356 if (left.Type == right.Type && TypeUtils.IsIntegerOrBool(left.Type)) {
2357 // conversion is not supported for binary ops on arithmetic types without operator overloading
2358 if (conversion != null) {
2359 throw Error.ConversionIsNotSupportedForArithmeticTypes();
2361 return new SimpleBinaryExpression(ExpressionType.AndAssign, left, right, left.Type);
2363 return GetUserDefinedAssignOperatorOrThrow(ExpressionType.AndAssign, "op_BitwiseAnd", left, right, conversion, true);
2365 return GetMethodBasedAssignOperator(ExpressionType.AndAssign, left, right, method, conversion, true);
2370 /// Creates a <see cref="BinaryExpression"/> that represents an bitwise OR operation.
2372 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
2373 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
2374 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.Or"/>
2375 /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
2376 public static BinaryExpression Or(Expression left, Expression right) {
2377 return Or(left, right, null);
2381 /// Creates a <see cref="BinaryExpression"/> that represents an bitwise OR operation.
2383 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
2384 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
2385 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
2386 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.Or"/>
2387 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
2389 public static BinaryExpression Or(Expression left, Expression right, MethodInfo method) {
2390 RequiresCanRead(left, "left");
2391 RequiresCanRead(right, "right");
2392 if (method == null) {
2393 if (left.Type == right.Type && TypeUtils.IsIntegerOrBool(left.Type)) {
2394 return new SimpleBinaryExpression(ExpressionType.Or, left, right, left.Type);
2396 return GetUserDefinedBinaryOperatorOrThrow(ExpressionType.Or, "op_BitwiseOr", left, right, true);
2398 return GetMethodBasedBinaryOperator(ExpressionType.Or, left, right, method, true);
2403 /// Creates a <see cref="BinaryExpression"/> that represents a bitwise OR assignment operation.
2405 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
2406 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
2407 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.OrAssign"/>
2408 /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
2409 public static BinaryExpression OrAssign(Expression left, Expression right) {
2410 return OrAssign(left, right, null, null);
2414 /// Creates a <see cref="BinaryExpression"/> that represents a bitwise OR assignment operation.
2416 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
2417 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
2418 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
2419 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.OrAssign"/>
2420 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
2422 public static BinaryExpression OrAssign(Expression left, Expression right, MethodInfo method) {
2423 return OrAssign(left, right, method, null);
2427 /// Creates a <see cref="BinaryExpression"/> that represents a bitwise OR assignment operation.
2429 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
2430 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
2431 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
2432 /// <param name="conversion">A <see cref="LambdaExpression"/> to set the <see cref="P:BinaryExpression.Conversion"/> property equal to.</param>
2433 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.OrAssign"/>
2434 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, <see cref="P:BinaryExpression.Method"/>,
2435 /// and <see cref="P:BinaryExpression.Conversion"/> properties set to the specified values.
2437 public static BinaryExpression OrAssign(Expression left, Expression right, MethodInfo method, LambdaExpression conversion) {
2438 RequiresCanRead(left, "left");
2439 RequiresCanWrite(left, "left");
2440 RequiresCanRead(right, "right");
2441 if (method == null) {
2442 if (left.Type == right.Type && TypeUtils.IsIntegerOrBool(left.Type)) {
2443 // conversion is not supported for binary ops on arithmetic types without operator overloading
2444 if (conversion != null) {
2445 throw Error.ConversionIsNotSupportedForArithmeticTypes();
2447 return new SimpleBinaryExpression(ExpressionType.OrAssign, left, right, left.Type);
2449 return GetUserDefinedAssignOperatorOrThrow(ExpressionType.OrAssign, "op_BitwiseOr", left, right, conversion, true);
2451 return GetMethodBasedAssignOperator(ExpressionType.OrAssign, left, right, method, conversion, true);
2455 /// Creates a <see cref="BinaryExpression"/> that represents a bitwise or logical XOR operation, using op_ExclusiveOr for user-defined types.
2457 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
2458 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
2459 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.ExclusiveOr"/>
2460 /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
2461 public static BinaryExpression ExclusiveOr(Expression left, Expression right) {
2462 return ExclusiveOr(left, right, null);
2466 /// Creates a <see cref="BinaryExpression"/> that represents a bitwise or logical XOR operation, using op_ExclusiveOr for user-defined types.
2468 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
2469 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
2470 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
2471 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.ExclusiveOr"/>
2472 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
2474 public static BinaryExpression ExclusiveOr(Expression left, Expression right, MethodInfo method) {
2475 RequiresCanRead(left, "left");
2476 RequiresCanRead(right, "right");
2477 if (method == null) {
2478 if (left.Type == right.Type && TypeUtils.IsIntegerOrBool(left.Type)) {
2479 return new SimpleBinaryExpression(ExpressionType.ExclusiveOr, left, right, left.Type);
2481 return GetUserDefinedBinaryOperatorOrThrow(ExpressionType.ExclusiveOr, "op_ExclusiveOr", left, right, true);
2483 return GetMethodBasedBinaryOperator(ExpressionType.ExclusiveOr, left, right, method, true);
2487 /// Creates a <see cref="BinaryExpression"/> that represents a bitwise or logical XOR assignment operation, using op_ExclusiveOr for user-defined types.
2489 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
2490 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
2491 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.ExclusiveOrAssign"/>
2492 /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
2493 public static BinaryExpression ExclusiveOrAssign(Expression left, Expression right) {
2494 return ExclusiveOrAssign(left, right, null, null);
2498 /// Creates a <see cref="BinaryExpression"/> that represents a bitwise or logical XOR assignment operation, using op_ExclusiveOr for user-defined types.
2500 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
2501 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
2502 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
2503 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.ExclusiveOrAssign"/>
2504 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
2506 public static BinaryExpression ExclusiveOrAssign(Expression left, Expression right, MethodInfo method) {
2507 return ExclusiveOrAssign(left, right, method, null);
2511 /// Creates a <see cref="BinaryExpression"/> that represents a bitwise or logical XOR assignment operation, using op_ExclusiveOr for user-defined types.
2513 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
2514 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
2515 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
2516 /// <param name="conversion">A <see cref="LambdaExpression"/> to set the <see cref="P:BinaryExpression.Conversion"/> property equal to.</param>
2517 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.ExclusiveOrAssign"/>
2518 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, <see cref="P:BinaryExpression.Method"/>,
2519 /// and <see cref="P:BinaryExpression.Conversion"/> properties set to the specified values.
2521 public static BinaryExpression ExclusiveOrAssign(Expression left, Expression right, MethodInfo method, LambdaExpression conversion) {
2522 RequiresCanRead(left, "left");
2523 RequiresCanWrite(left, "left");
2524 RequiresCanRead(right, "right");
2525 if (method == null) {
2526 if (left.Type == right.Type && TypeUtils.IsIntegerOrBool(left.Type)) {
2527 // conversion is not supported for binary ops on arithmetic types without operator overloading
2528 if (conversion != null) {
2529 throw Error.ConversionIsNotSupportedForArithmeticTypes();
2531 return new SimpleBinaryExpression(ExpressionType.ExclusiveOrAssign, left, right, left.Type);
2533 return GetUserDefinedAssignOperatorOrThrow(ExpressionType.ExclusiveOrAssign, "op_ExclusiveOr", left, right, conversion, true);
2535 return GetMethodBasedAssignOperator(ExpressionType.ExclusiveOrAssign, left, right, method, conversion, true);
2539 /// Creates a <see cref="BinaryExpression"/> that represents raising a number to a power.
2541 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
2542 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
2543 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.Power"/>
2544 /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
2545 public static BinaryExpression Power(Expression left, Expression right) {
2546 return Power(left, right, null);
2550 /// Creates a <see cref="BinaryExpression"/> that represents raising a number to a power.
2552 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
2553 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
2554 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
2555 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.Power"/>
2556 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
2558 public static BinaryExpression Power(Expression left, Expression right, MethodInfo method) {
2559 RequiresCanRead(left, "left");
2560 RequiresCanRead(right, "right");
2561 if (method == null) {
2562 Type mathType = typeof(System.Math);
2563 method = mathType.GetMethod("Pow", BindingFlags.Static | BindingFlags.Public);
2564 if (method == null) {
2565 throw Error.BinaryOperatorNotDefined(ExpressionType.Power, left.Type, right.Type);
2568 return GetMethodBasedBinaryOperator(ExpressionType.Power, left, right, method, true);
2573 /// Creates a <see cref="BinaryExpression"/> that represents raising an expression to a power and assigning the result back to the expression.
2575 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
2576 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
2577 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.PowerAssign"/>
2578 /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
2579 public static BinaryExpression PowerAssign(Expression left, Expression right) {
2580 return PowerAssign(left, right, null, null);
2584 /// Creates a <see cref="BinaryExpression"/> that represents raising an expression to a power and assigning the result back to the expression.
2586 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
2587 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
2588 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
2589 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.PowerAssign"/>
2590 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
2592 public static BinaryExpression PowerAssign(Expression left, Expression right, MethodInfo method) {
2593 return PowerAssign(left, right, method, null);
2597 /// Creates a <see cref="BinaryExpression"/> that represents raising an expression to a power and assigning the result back to the expression.
2599 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
2600 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
2601 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
2602 /// <param name="conversion">A <see cref="LambdaExpression"/> to set the <see cref="P:BinaryExpression.Conversion"/> property equal to.</param>
2603 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.PowerAssign"/>
2604 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, <see cref="P:BinaryExpression.Method"/>,
2605 /// and <see cref="P:BinaryExpression.Conversion"/> properties set to the specified values.
2607 public static BinaryExpression PowerAssign(Expression left, Expression right, MethodInfo method, LambdaExpression conversion) {
2608 RequiresCanRead(left, "left");
2609 RequiresCanWrite(left, "left");
2610 RequiresCanRead(right, "right");
2611 if (method == null) {
2612 Type mathType = typeof(System.Math);
2613 method = mathType.GetMethod("Pow", BindingFlags.Static | BindingFlags.Public);
2614 if (method == null) {
2615 throw Error.BinaryOperatorNotDefined(ExpressionType.PowerAssign, left.Type, right.Type);
2618 return GetMethodBasedAssignOperator(ExpressionType.PowerAssign, left, right, method, conversion, true);
2623 #region ArrayIndex Expression
2627 /// Creates a BinaryExpression that represents applying an array index operator to an array of rank one.
2629 /// <param name="array">An Expression to set the Left property equal to.</param>
2630 /// <param name="index">An Expression to set the Right property equal to.</param>
2631 /// <returns>A BinaryExpression that has the NodeType property equal to ArrayIndex and the Left and Right properties set to the specified values.</returns>
2632 public static BinaryExpression ArrayIndex(Expression array, Expression index) {
2633 RequiresCanRead(array, "array");
2634 RequiresCanRead(index, "index");
2635 if (index.Type != typeof(int)) {
2636 throw Error.ArgumentMustBeArrayIndexType();
2639 Type arrayType = array.Type;
2640 if (!arrayType.IsArray) {
2641 throw Error.ArgumentMustBeArray();
2643 if (arrayType.GetArrayRank() != 1) {
2644 throw Error.IncorrectNumberOfIndexes();
2647 return new SimpleBinaryExpression(ExpressionType.ArrayIndex, array, index, arrayType.GetElementType());