2 /* ****************************************************************************
4 * Copyright (c) Microsoft Corporation.
6 * This source code is subject to terms and conditions of the Microsoft Public License. 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 Microsoft Public License, 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 Microsoft Public License.
12 * You must not remove this notice, or any other, from this software.
15 * ***************************************************************************/
16 using System; using Microsoft;
19 using System.Collections.Generic;
20 using System.Diagnostics;
22 using System.Dynamic.Utils;
24 using Microsoft.Scripting.Utils;
26 using System.Reflection;
29 namespace System.Linq.Expressions {
31 namespace Microsoft.Linq.Expressions {
35 /// Represents an expression that has a binary operator.
38 [DebuggerTypeProxy(typeof(Expression.BinaryExpressionProxy))]
40 public class BinaryExpression : Expression {
41 private readonly Expression _left;
42 private readonly Expression _right;
44 internal BinaryExpression(Expression left, Expression right) {
50 /// Gets a value that indicates whether the expression tree node can be reduced.
52 public override bool CanReduce {
54 // Only OpAssignments are reducible.
55 return IsOpAssignment(NodeType);
59 private static bool IsOpAssignment(ExpressionType op) {
61 case ExpressionType.AddAssign:
62 case ExpressionType.SubtractAssign:
63 case ExpressionType.MultiplyAssign:
64 case ExpressionType.AddAssignChecked:
65 case ExpressionType.SubtractAssignChecked:
66 case ExpressionType.MultiplyAssignChecked:
67 case ExpressionType.DivideAssign:
68 case ExpressionType.ModuloAssign:
69 case ExpressionType.PowerAssign:
70 case ExpressionType.AndAssign:
71 case ExpressionType.OrAssign:
72 case ExpressionType.RightShiftAssign:
73 case ExpressionType.LeftShiftAssign:
74 case ExpressionType.ExclusiveOrAssign:
80 /// Gets the right operand of the binary operation.
82 public Expression Right {
83 get { return _right; }
86 /// Gets the left operand of the binary operation.
88 public Expression Left {
92 /// Gets the implementing method for the binary operation.
94 public MethodInfo Method {
95 get { return GetMethod(); }
98 internal virtual MethodInfo GetMethod() {
103 /// Reduces the binary expression node to a simpler expression.
104 /// If CanReduce returns true, this should return a valid expression.
105 /// This method is allowed to return another node which itself
108 /// <returns>The reduced expression.</returns>
109 public override Expression Reduce() {
110 // Only reduce OpAssignment expressions.
111 if (IsOpAssignment(NodeType)) {
112 switch (_left.NodeType) {
113 case ExpressionType.MemberAccess:
114 return ReduceMember();
116 case ExpressionType.Index:
117 return ReduceIndex();
120 return ReduceVariable();
126 // Return the corresponding Op of an assignment op.
127 private static ExpressionType GetBinaryOpFromAssignmentOp(ExpressionType op) {
128 Debug.Assert(IsOpAssignment(op));
130 case ExpressionType.AddAssign:
131 return ExpressionType.Add;
132 case ExpressionType.AddAssignChecked:
133 return ExpressionType.AddChecked;
134 case ExpressionType.SubtractAssign:
135 return ExpressionType.Subtract;
136 case ExpressionType.SubtractAssignChecked:
137 return ExpressionType.SubtractChecked;
138 case ExpressionType.MultiplyAssign:
139 return ExpressionType.Multiply;
140 case ExpressionType.MultiplyAssignChecked:
141 return ExpressionType.MultiplyChecked;
142 case ExpressionType.DivideAssign:
143 return ExpressionType.Divide;
144 case ExpressionType.ModuloAssign:
145 return ExpressionType.Modulo;
146 case ExpressionType.PowerAssign:
147 return ExpressionType.Power;
148 case ExpressionType.AndAssign:
149 return ExpressionType.And;
150 case ExpressionType.OrAssign:
151 return ExpressionType.Or;
152 case ExpressionType.RightShiftAssign:
153 return ExpressionType.RightShift;
154 case ExpressionType.LeftShiftAssign:
155 return ExpressionType.LeftShift;
156 case ExpressionType.ExclusiveOrAssign:
157 return ExpressionType.ExclusiveOr;
160 throw Error.InvalidOperation("op");
165 private Expression ReduceVariable() {
167 // ... is reduced into ...
169 ExpressionType op = GetBinaryOpFromAssignmentOp(NodeType);
170 Expression r = Expression.MakeBinary(op, _left, _right, false, Method);
171 LambdaExpression conversion = GetConversion();
172 if (conversion != null) {
173 r = Expression.Invoke(conversion, r);
175 return Expression.Assign(_left, r);
178 private Expression ReduceMember() {
179 MemberExpression member = (MemberExpression)_left;
181 if (member.Expression == null) {
182 // static member, reduce the same as variable
183 return ReduceVariable();
186 // ... is reduced into ...
188 // temp2 = temp1.b (op) r
191 ParameterExpression temp1 = Variable(member.Expression.Type, "temp1");
194 Expression e1 = Expression.Assign(temp1, member.Expression);
196 // 2. temp2 = temp1.b (op) r
197 ExpressionType op = GetBinaryOpFromAssignmentOp(NodeType);
198 Expression e2 = Expression.MakeBinary(op, Expression.MakeMemberAccess(temp1, member.Member), _right, false, Method);
199 LambdaExpression conversion = GetConversion();
200 if (conversion != null) {
201 e2 = Expression.Invoke(conversion, e2);
203 ParameterExpression temp2 = Variable(e2.Type, "temp2");
204 e2 = Expression.Assign(temp2, e2);
206 // 3. temp1.b = temp2
207 Expression e3 = Expression.Assign(Expression.MakeMemberAccess(temp1, member.Member), temp2);
210 Expression e4 = temp2;
212 return Expression.Block(
213 new ParameterExpression[] { temp1, temp2 },
219 private Expression ReduceIndex() {
220 // left[a0, a1, ... aN] (op)= r
222 // ... is reduced into ...
228 // tempValue = tempObj[tempArg0, ... tempArgN] (op) r
229 // tempObj[tempArg0, ... tempArgN] = tempValue
231 var index = (IndexExpression)_left;
233 var vars = new List<ParameterExpression>(index.Arguments.Count + 2);
234 var exprs = new List<Expression>(index.Arguments.Count + 3);
236 var tempObj = Expression.Variable(index.Object.Type, "tempObj");
238 exprs.Add(Expression.Assign(tempObj, index.Object));
240 var tempArgs = new List<Expression>(index.Arguments.Count);
241 foreach (var arg in index.Arguments) {
242 var tempArg = Expression.Variable(arg.Type, "tempArg" + tempArgs.Count);
244 tempArgs.Add(tempArg);
245 exprs.Add(Expression.Assign(tempArg, arg));
248 var tempIndex = Expression.MakeIndex(tempObj, index.Indexer, tempArgs);
250 // tempValue = tempObj[tempArg0, ... tempArgN] (op) r
251 ExpressionType binaryOp = GetBinaryOpFromAssignmentOp(NodeType);
252 Expression op = Expression.MakeBinary(binaryOp, tempIndex, _right, false, Method);
253 LambdaExpression conversion = GetConversion();
254 if (conversion != null) {
255 op = Expression.Invoke(conversion, op);
257 var tempValue = Expression.Variable(op.Type, "tempValue");
259 exprs.Add(Expression.Assign(tempValue, op));
261 // tempObj[tempArg0, ... tempArgN] = tempValue
262 exprs.Add(Expression.Assign(tempIndex, tempValue));
264 return Expression.Block(vars, exprs);
268 /// Gets the type conversion function that is used by a coalescing or compound assignment operation.
270 public LambdaExpression Conversion {
271 get { return GetConversion(); }
274 internal virtual LambdaExpression GetConversion() {
278 /// Gets a value that indicates whether the expression tree node represents a lifted call to an operator.
280 public bool IsLifted {
282 if (NodeType == ExpressionType.Coalesce || NodeType == ExpressionType.Assign) {
285 if (TypeUtils.IsNullableType(_left.Type)) {
286 MethodInfo method = GetMethod();
287 return method == null ||
288 !TypeUtils.AreEquivalent(method.GetParametersCached()[0].ParameterType.GetNonRefType(), _left.Type);
294 /// 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.
296 public bool IsLiftedToNull {
298 return IsLifted && TypeUtils.IsNullableType(Type);
302 internal override Expression Accept(ExpressionVisitor visitor) {
303 return visitor.VisitBinary(this);
306 internal static Expression Create(ExpressionType nodeType, Expression left, Expression right, Type type, MethodInfo method, LambdaExpression conversion) {
307 if (nodeType == ExpressionType.Assign) {
308 Debug.Assert(method == null && TypeUtils.AreEquivalent(type, left.Type));
309 return new AssignBinaryExpression(left, right);
311 if (conversion != null) {
312 Debug.Assert(method == null && TypeUtils.AreEquivalent(type, right.Type) && nodeType == ExpressionType.Coalesce);
313 return new CoalesceConversionBinaryExpression(left, right, conversion);
315 if (method != null) {
316 return new MethodBinaryExpression(nodeType, left, right, type, method);
318 if (type == typeof(bool)) {
319 return new LogicalBinaryExpression(nodeType, left, right);
321 return new SimpleBinaryExpression(nodeType, left, right, type);
324 internal bool IsLiftedLogical {
326 Type left = _left.Type;
327 Type right = _right.Type;
328 MethodInfo method = GetMethod();
329 ExpressionType kind = NodeType;
332 (kind == ExpressionType.AndAlso || kind == ExpressionType.OrElse) &&
333 TypeUtils.AreEquivalent(right, left) &&
334 TypeUtils.IsNullableType(left) &&
336 TypeUtils.AreEquivalent(method.ReturnType, TypeUtils.GetNonNullableType(left));
340 internal bool IsReferenceComparison {
342 Type left = _left.Type;
343 Type right = _right.Type;
344 MethodInfo method = GetMethod();
345 ExpressionType kind = NodeType;
347 return (kind == ExpressionType.Equal || kind == ExpressionType.NotEqual) &&
348 method == null && !left.IsValueType && !right.IsValueType;
353 // For a userdefined type T which has op_False defined and L, R are
354 // nullable, (L AndAlso R) is computed as:
357 // ? T.op_False(L.GetValueOrDefault())
360 // ? (T?)(T.op_BitwiseAnd(L.GetValueOrDefault(), R.GetValueOrDefault()))
364 // For a userdefined type T which has op_True defined and L, R are
365 // nullable, (L OrElse R) is computed as:
368 // ? T.op_True(L.GetValueOrDefault())
371 // ? (T?)(T.op_BitwiseOr(L.GetValueOrDefault(), R.GetValueOrDefault()))
376 // This is the same behavior as VB. If you think about it, it makes
377 // sense: it's combining the normal pattern for short-circuiting
378 // operators, with the normal pattern for lifted operations: if either
379 // of the operands is null, the result is also null.
381 internal Expression ReduceUserdefinedLifted() {
382 Debug.Assert(IsLiftedLogical);
384 var left = Parameter(_left.Type, "left");
385 var right = Parameter(Right.Type, "right");
386 string opName = NodeType == ExpressionType.AndAlso ? "op_False" : "op_True";
387 MethodInfo opTrueFalse = TypeUtils.GetBooleanOperator(Method.DeclaringType, opName);
388 Debug.Assert(opTrueFalse != null);
394 Property(left, "HasValue"),
396 Call(opTrueFalse, Call(left, "GetValueOrDefault", null)),
400 Assign(right, _right),
402 Property(right, "HasValue"),
406 Call(left, "GetValueOrDefault", null),
407 Call(right, "GetValueOrDefault", null)
421 // Optimized representation of simple logical expressions:
422 // && || == != > < >= <=
423 internal sealed class LogicalBinaryExpression : BinaryExpression {
424 private readonly ExpressionType _nodeType;
426 internal LogicalBinaryExpression(ExpressionType nodeType, Expression left, Expression right)
427 : base(left, right) {
428 _nodeType = nodeType;
431 public sealed override Type Type {
432 get { return typeof(bool); }
435 public sealed override ExpressionType NodeType {
436 get { return _nodeType; }
440 // Optimized assignment node, only holds onto children
441 internal sealed class AssignBinaryExpression : BinaryExpression {
442 internal AssignBinaryExpression(Expression left, Expression right)
443 : base(left, right) {
446 public sealed override Type Type {
447 get { return Left.Type; }
450 public sealed override ExpressionType NodeType {
451 get { return ExpressionType.Assign; }
455 // Coalesce with conversion
456 // This is not a frequently used node, but rather we want to save every
457 // other BinaryExpression from holding onto the null conversion lambda
458 internal sealed class CoalesceConversionBinaryExpression : BinaryExpression {
459 private readonly LambdaExpression _conversion;
461 internal CoalesceConversionBinaryExpression(Expression left, Expression right, LambdaExpression conversion)
462 : base(left, right) {
463 _conversion = conversion;
466 internal override LambdaExpression GetConversion() {
470 public sealed override ExpressionType NodeType {
471 get { return ExpressionType.Coalesce; }
474 public sealed override Type Type {
475 get { return Right.Type; }
479 // OpAssign with conversion
480 // This is not a frequently used node, but rather we want to save every
481 // other BinaryExpression from holding onto the null conversion lambda
482 internal sealed class OpAssignMethodConversionBinaryExpression : MethodBinaryExpression {
483 private readonly LambdaExpression _conversion;
485 internal OpAssignMethodConversionBinaryExpression(ExpressionType nodeType, Expression left, Expression right, Type type, MethodInfo method, LambdaExpression conversion)
486 : base(nodeType, left, right, type, method) {
487 _conversion = conversion;
490 internal override LambdaExpression GetConversion() {
495 // Class that handles most binary expressions
496 // If needed, it can be optimized even more (often Type == left.Type)
497 internal class SimpleBinaryExpression : BinaryExpression {
498 private readonly ExpressionType _nodeType;
499 private readonly Type _type;
501 internal SimpleBinaryExpression(ExpressionType nodeType, Expression left, Expression right, Type type)
502 : base(left, right) {
503 _nodeType = nodeType;
507 public sealed override ExpressionType NodeType {
508 get { return _nodeType; }
511 public sealed override Type Type {
512 get { return _type; }
516 // Class that handles binary expressions with a method
517 // If needed, it can be optimized even more (often Type == method.ReturnType)
518 internal class MethodBinaryExpression : SimpleBinaryExpression {
519 private readonly MethodInfo _method;
521 internal MethodBinaryExpression(ExpressionType nodeType, Expression left, Expression right, Type type, MethodInfo method)
522 : base(nodeType, left, right, type) {
526 internal override MethodInfo GetMethod() {
531 public partial class Expression {
536 /// Creates a <see cref="BinaryExpression"/> that represents an assignment operation.
538 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
539 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
540 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see ref="F:ExpressionType.Assign"/>
541 /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.
543 public static BinaryExpression Assign(Expression left, Expression right) {
544 RequiresCanWrite(left, "left");
545 RequiresCanRead(right, "right");
546 TypeUtils.ValidateType(left.Type);
547 TypeUtils.ValidateType(right.Type);
548 if (!TypeUtils.AreReferenceAssignable(left.Type, right.Type)) {
549 throw Error.ExpressionTypeDoesNotMatchAssignment(right.Type, left.Type);
551 return new AssignBinaryExpression(left, right);
557 private static BinaryExpression GetUserDefinedBinaryOperator(ExpressionType binaryType, string name, Expression left, Expression right, bool liftToNull) {
558 // try exact match first
559 MethodInfo method = GetUserDefinedBinaryOperator(binaryType, left.Type, right.Type, name);
560 if (method != null) {
561 return new MethodBinaryExpression(binaryType, left, right, method.ReturnType, method);
564 if (TypeUtils.IsNullableType(left.Type) && TypeUtils.IsNullableType(right.Type)) {
565 Type nnLeftType = TypeUtils.GetNonNullableType(left.Type);
566 Type nnRightType = TypeUtils.GetNonNullableType(right.Type);
567 method = GetUserDefinedBinaryOperator(binaryType, nnLeftType, nnRightType, name);
568 if (method != null && method.ReturnType.IsValueType && !TypeUtils.IsNullableType(method.ReturnType)) {
569 if (method.ReturnType != typeof(bool) || liftToNull) {
570 return new MethodBinaryExpression(binaryType, left, right, TypeUtils.GetNullableType(method.ReturnType), method);
572 return new MethodBinaryExpression(binaryType, left, right, typeof(bool), method);
580 private static BinaryExpression GetMethodBasedBinaryOperator(ExpressionType binaryType, Expression left, Expression right, MethodInfo method, bool liftToNull) {
581 System.Diagnostics.Debug.Assert(method != null);
582 ValidateOperator(method);
583 ParameterInfo[] pms = method.GetParametersCached();
585 throw Error.IncorrectNumberOfMethodCallArguments(method);
586 if (ParameterIsAssignable(pms[0], left.Type) && ParameterIsAssignable(pms[1], right.Type)) {
587 ValidateParamswithOperandsOrThrow(pms[0].ParameterType, left.Type, binaryType, method.Name);
588 ValidateParamswithOperandsOrThrow(pms[1].ParameterType, right.Type, binaryType, method.Name);
589 return new MethodBinaryExpression(binaryType, left, right, method.ReturnType, method);
592 // check for lifted call
593 if (TypeUtils.IsNullableType(left.Type) && TypeUtils.IsNullableType(right.Type) &&
594 ParameterIsAssignable(pms[0], TypeUtils.GetNonNullableType(left.Type)) &&
595 ParameterIsAssignable(pms[1], TypeUtils.GetNonNullableType(right.Type)) &&
596 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);
603 throw Error.OperandTypesDoNotMatchParameters(binaryType, method.Name);
606 private static BinaryExpression GetMethodBasedAssignOperator(ExpressionType binaryType, Expression left, Expression right, MethodInfo method, LambdaExpression conversion, bool liftToNull) {
607 BinaryExpression b = GetMethodBasedBinaryOperator(binaryType, left, right, method, liftToNull);
608 if (conversion == null) {
609 // return type must be assignable back to the left type
610 if (!TypeUtils.AreReferenceAssignable(left.Type, b.Type)) {
611 throw Error.UserDefinedOpMustHaveValidReturnType(binaryType, b.Method.Name);
614 // add the conversion to the result
615 ValidateOpAssignConversionLambda(conversion, b.Left, b.Method, b.NodeType);
616 b = new OpAssignMethodConversionBinaryExpression(b.NodeType, b.Left, b.Right, b.Left.Type, b.Method, conversion);
622 private static BinaryExpression GetUserDefinedBinaryOperatorOrThrow(ExpressionType binaryType, string name, Expression left, Expression right, bool liftToNull) {
623 BinaryExpression b = GetUserDefinedBinaryOperator(binaryType, name, left, right, liftToNull);
625 ParameterInfo[] pis = b.Method.GetParametersCached();
626 ValidateParamswithOperandsOrThrow(pis[0].ParameterType, left.Type, binaryType, name);
627 ValidateParamswithOperandsOrThrow(pis[1].ParameterType, right.Type, binaryType, name);
630 throw Error.BinaryOperatorNotDefined(binaryType, left.Type, right.Type);
633 private static BinaryExpression GetUserDefinedAssignOperatorOrThrow(ExpressionType binaryType, string name, Expression left, Expression right, LambdaExpression conversion, bool liftToNull) {
634 BinaryExpression b = GetUserDefinedBinaryOperatorOrThrow(binaryType, name, left, right, liftToNull);
635 if (conversion == null) {
636 // return type must be assignable back to the left type
637 if (!TypeUtils.AreReferenceAssignable(left.Type, b.Type)) {
638 throw Error.UserDefinedOpMustHaveValidReturnType(binaryType, b.Method.Name);
641 // add the conversion to the result
642 ValidateOpAssignConversionLambda(conversion, b.Left, b.Method, b.NodeType);
643 b = new OpAssignMethodConversionBinaryExpression(b.NodeType, b.Left, b.Right, b.Left.Type, b.Method, conversion);
649 private static MethodInfo GetUserDefinedBinaryOperator(ExpressionType binaryType, Type leftType, Type rightType, string name) {
650 // UNDONE: This algorithm is wrong, we should be checking for uniqueness and erroring if
651 // UNDONE: it is defined on both types.
652 Type[] types = new Type[] { leftType, rightType };
653 Type nnLeftType = TypeUtils.GetNonNullableType(leftType);
654 Type nnRightType = TypeUtils.GetNonNullableType(rightType);
655 BindingFlags flags = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
656 MethodInfo method = nnLeftType.GetMethodValidated(name, flags, null, types, null);
657 if (method == null && !TypeUtils.AreEquivalent(leftType, rightType)) {
658 method = nnRightType.GetMethodValidated(name, flags, null, types, null);
661 if (IsLiftingConditionalLogicalOperator(leftType, rightType, method, binaryType)) {
662 method = GetUserDefinedBinaryOperator(binaryType, nnLeftType, nnRightType, name);
668 private static bool IsLiftingConditionalLogicalOperator(Type left, Type right, MethodInfo method, ExpressionType binaryType) {
669 return TypeUtils.IsNullableType(right) &&
670 TypeUtils.IsNullableType(left) &&
672 (binaryType == ExpressionType.AndAlso || binaryType == ExpressionType.OrElse);
676 internal static bool ParameterIsAssignable(ParameterInfo pi, Type argType) {
677 Type pType = pi.ParameterType;
679 pType = pType.GetElementType();
680 return TypeUtils.AreReferenceAssignable(pType, argType);
684 private static void ValidateParamswithOperandsOrThrow(Type paramType, Type operandType, ExpressionType exprType, string name) {
685 if (TypeUtils.IsNullableType(paramType) && !TypeUtils.IsNullableType(operandType)) {
686 throw Error.OperandTypesDoNotMatchParameters(exprType, name);
691 private static void ValidateOperator(MethodInfo method) {
692 System.Diagnostics.Debug.Assert(method != null);
693 ValidateMethodInfo(method);
694 if (!method.IsStatic)
695 throw Error.UserDefinedOperatorMustBeStatic(method);
696 if (method.ReturnType == typeof(void))
697 throw Error.UserDefinedOperatorMustNotBeVoid(method);
701 private static void ValidateMethodInfo(MethodInfo method) {
702 if (method.IsGenericMethodDefinition)
703 throw Error.MethodIsGeneric(method);
704 if (method.ContainsGenericParameters)
705 throw Error.MethodContainsGenericParameters(method);
709 private static bool IsNullComparison(Expression left, Expression right) {
710 // If we have x==null, x!=null, null==x or null!=x where x is
711 // nullable but not null, then this is treated as a call to x.HasValue
712 // and is legal even if there is no equality operator defined on the
714 if (IsNullConstant(left) && !IsNullConstant(right) && TypeUtils.IsNullableType(right.Type)) {
717 if (IsNullConstant(right) && !IsNullConstant(left) && TypeUtils.IsNullableType(left.Type)) {
724 // Note: this has different meaning than ConstantCheck.IsNull
725 // That function attempts to determine if the result of a tree will be
726 // null at runtime. This function is used at tree construction time and
727 // only looks for a ConstantExpression with a null Value. It can't
728 // become "smarter" or that would break tree construction.
729 private static bool IsNullConstant(Expression e) {
730 var c = e as ConstantExpression;
731 return c != null && c.Value == null;
735 private static void ValidateUserDefinedConditionalLogicOperator(ExpressionType nodeType, Type left, Type right, MethodInfo method) {
736 ValidateOperator(method);
737 ParameterInfo[] pms = method.GetParametersCached();
739 throw Error.IncorrectNumberOfMethodCallArguments(method);
740 if (!ParameterIsAssignable(pms[0], left)) {
741 if (!(TypeUtils.IsNullableType(left) && ParameterIsAssignable(pms[0], TypeUtils.GetNonNullableType(left))))
742 throw Error.OperandTypesDoNotMatchParameters(nodeType, method.Name);
744 if (!ParameterIsAssignable(pms[1], right)) {
745 if (!(TypeUtils.IsNullableType(right) && ParameterIsAssignable(pms[1], TypeUtils.GetNonNullableType(right))))
746 throw Error.OperandTypesDoNotMatchParameters(nodeType, method.Name);
748 if (pms[0].ParameterType != pms[1].ParameterType) {
749 throw Error.UserDefinedOpMustHaveConsistentTypes(nodeType, method.Name);
751 if (method.ReturnType != pms[0].ParameterType) {
752 throw Error.UserDefinedOpMustHaveConsistentTypes(nodeType, method.Name);
754 if (IsValidLiftedConditionalLogicalOperator(left, right, pms)) {
755 left = TypeUtils.GetNonNullableType(left);
756 right = TypeUtils.GetNonNullableType(left);
758 MethodInfo opTrue = TypeUtils.GetBooleanOperator(method.DeclaringType, "op_True");
759 MethodInfo opFalse = TypeUtils.GetBooleanOperator(method.DeclaringType, "op_False");
760 if (opTrue == null || opTrue.ReturnType != typeof(bool) ||
761 opFalse == null || opFalse.ReturnType != typeof(bool)) {
762 throw Error.LogicalOperatorMustHaveBooleanOperators(nodeType, method.Name);
764 VerifyOpTrueFalse(nodeType, left, opFalse);
765 VerifyOpTrueFalse(nodeType, left, opTrue);
768 private static void VerifyOpTrueFalse(ExpressionType nodeType, Type left, MethodInfo opTrue) {
769 ParameterInfo[] pmsOpTrue = opTrue.GetParametersCached();
770 if (pmsOpTrue.Length != 1)
771 throw Error.IncorrectNumberOfMethodCallArguments(opTrue);
773 if (!ParameterIsAssignable(pmsOpTrue[0], left)) {
774 if (!(TypeUtils.IsNullableType(left) && ParameterIsAssignable(pmsOpTrue[0], TypeUtils.GetNonNullableType(left))))
775 throw Error.OperandTypesDoNotMatchParameters(nodeType, opTrue.Name);
779 private static bool IsValidLiftedConditionalLogicalOperator(Type left, Type right, ParameterInfo[] pms) {
780 return TypeUtils.AreEquivalent(left, right) &&
781 TypeUtils.IsNullableType(right) &&
782 TypeUtils.AreEquivalent(pms[1].ParameterType, TypeUtils.GetNonNullableType(right));
787 /// Creates a BinaryExpression, given the left and right operands, by calling an appropriate factory method.
789 /// <param name="binaryType">The ExpressionType that specifies the type of binary operation.</param>
790 /// <param name="left">An Expression that represents the left operand.</param>
791 /// <param name="right">An Expression that represents the right operand.</param>
792 /// <returns>The BinaryExpression that results from calling the appropriate factory method.</returns>
793 public static BinaryExpression MakeBinary(ExpressionType binaryType, Expression left, Expression right) {
794 return MakeBinary(binaryType, left, right, false, null, null);
798 /// Creates a BinaryExpression, given the left and right operands, by calling an appropriate factory method.
800 /// <param name="binaryType">The ExpressionType that specifies the type of binary operation.</param>
801 /// <param name="left">An Expression that represents the left operand.</param>
802 /// <param name="right">An Expression that represents the right operand.</param>
803 /// <param name="liftToNull">true to set IsLiftedToNull to true; false to set IsLiftedToNull to false.</param>
804 /// <param name="method">A MethodInfo that specifies the implementing method.</param>
805 /// <returns>The BinaryExpression that results from calling the appropriate factory method.</returns>
806 public static BinaryExpression MakeBinary(ExpressionType binaryType, Expression left, Expression right, bool liftToNull, MethodInfo method) {
807 return MakeBinary(binaryType, left, right, liftToNull, method, null);
812 /// Creates a BinaryExpression, given the left and right operands, by calling an appropriate factory method.
814 /// <param name="binaryType">The ExpressionType that specifies the type of binary operation.</param>
815 /// <param name="left">An Expression that represents the left operand.</param>
816 /// <param name="right">An Expression that represents the right operand.</param>
817 /// <param name="liftToNull">true to set IsLiftedToNull to true; false to set IsLiftedToNull to false.</param>
818 /// <param name="method">A MethodInfo that specifies the implementing method.</param>
819 /// <param name="conversion">A LambdaExpression that represents a type conversion function. This parameter is used if binaryType is Coalesce or compound assignment.</param>
820 /// <returns>The BinaryExpression that results from calling the appropriate factory method.</returns>
821 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
822 public static BinaryExpression MakeBinary(ExpressionType binaryType, Expression left, Expression right, bool liftToNull, MethodInfo method, LambdaExpression conversion) {
823 switch (binaryType) {
824 case ExpressionType.Add:
825 return Add(left, right, method);
826 case ExpressionType.AddChecked:
827 return AddChecked(left, right, method);
828 case ExpressionType.Subtract:
829 return Subtract(left, right, method);
830 case ExpressionType.SubtractChecked:
831 return SubtractChecked(left, right, method);
832 case ExpressionType.Multiply:
833 return Multiply(left, right, method);
834 case ExpressionType.MultiplyChecked:
835 return MultiplyChecked(left, right, method);
836 case ExpressionType.Divide:
837 return Divide(left, right, method);
838 case ExpressionType.Modulo:
839 return Modulo(left, right, method);
840 case ExpressionType.Power:
841 return Power(left, right, method);
842 case ExpressionType.And:
843 return And(left, right, method);
844 case ExpressionType.AndAlso:
845 return AndAlso(left, right, method);
846 case ExpressionType.Or:
847 return Or(left, right, method);
848 case ExpressionType.OrElse:
849 return OrElse(left, right, method);
850 case ExpressionType.LessThan:
851 return LessThan(left, right, liftToNull, method);
852 case ExpressionType.LessThanOrEqual:
853 return LessThanOrEqual(left, right, liftToNull, method);
854 case ExpressionType.GreaterThan:
855 return GreaterThan(left, right, liftToNull, method);
856 case ExpressionType.GreaterThanOrEqual:
857 return GreaterThanOrEqual(left, right, liftToNull, method);
858 case ExpressionType.Equal:
859 return Equal(left, right, liftToNull, method);
860 case ExpressionType.NotEqual:
861 return NotEqual(left, right, liftToNull, method);
862 case ExpressionType.ExclusiveOr:
863 return ExclusiveOr(left, right, method);
864 case ExpressionType.Coalesce:
865 return Coalesce(left, right, conversion);
866 case ExpressionType.ArrayIndex:
867 return ArrayIndex(left, right);
868 case ExpressionType.RightShift:
869 return RightShift(left, right, method);
870 case ExpressionType.LeftShift:
871 return LeftShift(left, right, method);
872 case ExpressionType.Assign:
873 return Assign(left, right);
874 case ExpressionType.AddAssign:
875 return AddAssign(left, right, method, conversion);
876 case ExpressionType.AndAssign:
877 return AndAssign(left, right, method, conversion);
878 case ExpressionType.DivideAssign:
879 return DivideAssign(left, right, method, conversion);
880 case ExpressionType.ExclusiveOrAssign:
881 return ExclusiveOrAssign(left, right, method, conversion);
882 case ExpressionType.LeftShiftAssign:
883 return LeftShiftAssign(left, right, method, conversion);
884 case ExpressionType.ModuloAssign:
885 return ModuloAssign(left, right, method, conversion);
886 case ExpressionType.MultiplyAssign:
887 return MultiplyAssign(left, right, method, conversion);
888 case ExpressionType.OrAssign:
889 return OrAssign(left, right, method, conversion);
890 case ExpressionType.PowerAssign:
891 return PowerAssign(left, right, method, conversion);
892 case ExpressionType.RightShiftAssign:
893 return RightShiftAssign(left, right, method, conversion);
894 case ExpressionType.SubtractAssign:
895 return SubtractAssign(left, right, method, conversion);
896 case ExpressionType.AddAssignChecked:
897 return AddAssignChecked(left, right, method, conversion);
898 case ExpressionType.SubtractAssignChecked:
899 return SubtractAssignChecked(left, right, method, conversion);
900 case ExpressionType.MultiplyAssignChecked:
901 return MultiplyAssignChecked(left, right, method, conversion);
903 throw Error.UnhandledBinary(binaryType);
907 #region Equality Operators
911 /// Creates a <see cref="BinaryExpression"/> that represents an equality comparison.
913 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
914 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
915 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.Equal"/>
916 /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
917 public static BinaryExpression Equal(Expression left, Expression right) {
918 return Equal(left, right, false, null);
922 /// Creates a <see cref="BinaryExpression"/> that represents an equality comparison.
924 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
925 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
926 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
927 /// <param name="liftToNull">true to set IsLiftedToNull to true; false to set IsLiftedToNull to false.</param>
928 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.Equal"/>
929 /// 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.
931 public static BinaryExpression Equal(Expression left, Expression right, bool liftToNull, MethodInfo method) {
932 RequiresCanRead(left, "left");
933 RequiresCanRead(right, "right");
934 if (method == null) {
935 return GetEqualityComparisonOperator(ExpressionType.Equal, "op_Equality", left, right, liftToNull);
937 return GetMethodBasedBinaryOperator(ExpressionType.Equal, left, right, method, liftToNull);
941 /// Creates a <see cref="BinaryExpression"/> that represents a reference equality comparison.
943 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
944 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
945 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.Equal"/>
946 /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.
948 public static BinaryExpression ReferenceEqual(Expression left, Expression right) {
949 RequiresCanRead(left, "left");
950 RequiresCanRead(right, "right");
951 if (TypeUtils.HasReferenceEquality(left.Type, right.Type)) {
952 return new LogicalBinaryExpression(ExpressionType.Equal, left, right);
954 throw Error.ReferenceEqualityNotDefined(left.Type, right.Type);
958 /// Creates a <see cref="BinaryExpression"/> that represents an inequality comparison.
960 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
961 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
962 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.NotEqual"/>
963 /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
964 public static BinaryExpression NotEqual(Expression left, Expression right) {
965 return NotEqual(left, right, false, null);
969 /// Creates a <see cref="BinaryExpression"/> that represents an inequality 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 /// <param name="liftToNull">true to set IsLiftedToNull to true; false to set IsLiftedToNull to false.</param>
974 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
975 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.NotEqual"/>
976 /// 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.
978 public static BinaryExpression NotEqual(Expression left, Expression right, bool liftToNull, MethodInfo method) {
979 RequiresCanRead(left, "left");
980 RequiresCanRead(right, "right");
981 if (method == null) {
982 return GetEqualityComparisonOperator(ExpressionType.NotEqual, "op_Inequality", left, right, liftToNull);
984 return GetMethodBasedBinaryOperator(ExpressionType.NotEqual, left, right, method, liftToNull);
988 /// Creates a <see cref="BinaryExpression"/> that represents a reference inequality comparison.
990 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
991 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
992 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.NotEqual"/>
993 /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.
995 public static BinaryExpression ReferenceNotEqual(Expression left, Expression right) {
996 RequiresCanRead(left, "left");
997 RequiresCanRead(right, "right");
998 if (TypeUtils.HasReferenceEquality(left.Type, right.Type)) {
999 return new LogicalBinaryExpression(ExpressionType.NotEqual, left, right);
1001 throw Error.ReferenceEqualityNotDefined(left.Type, right.Type);
1004 private static BinaryExpression GetEqualityComparisonOperator(ExpressionType binaryType, string opName, Expression left, Expression right, bool liftToNull) {
1005 // known comparison - numeric types, bools, object, enums
1006 if (left.Type == right.Type && (TypeUtils.IsNumeric(left.Type) ||
1007 left.Type == typeof(object) ||
1008 TypeUtils.IsBool(left.Type) ||
1009 TypeUtils.GetNonNullableType(left.Type).IsEnum)) {
1010 if (TypeUtils.IsNullableType(left.Type) && liftToNull) {
1011 return new SimpleBinaryExpression(binaryType, left, right, typeof(bool?));
1013 return new LogicalBinaryExpression(binaryType, left, right);
1016 // look for user defined operator
1017 BinaryExpression b = GetUserDefinedBinaryOperator(binaryType, opName, left, right, liftToNull);
1021 if (TypeUtils.HasBuiltInEqualityOperator(left.Type, right.Type) || IsNullComparison(left, right)) {
1022 if (TypeUtils.IsNullableType(left.Type) && liftToNull) {
1023 return new SimpleBinaryExpression(binaryType, left, right, typeof(bool?));
1025 return new LogicalBinaryExpression(binaryType, left, right);
1028 throw Error.BinaryOperatorNotDefined(binaryType, left.Type, right.Type);
1033 #region Comparison Expressions
1037 /// Creates a <see cref="BinaryExpression"/> that represents a "greater than" numeric comparison.
1039 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1040 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1041 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.GreaterThan"/>
1042 /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
1043 public static BinaryExpression GreaterThan(Expression left, Expression right) {
1044 return GreaterThan(left, right, false, null);
1048 /// Creates a <see cref="BinaryExpression"/> that represents a "greater than" numeric comparison.
1050 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1051 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1052 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
1053 /// <param name="liftToNull">true to set IsLiftedToNull to true; false to set IsLiftedToNull to false.</param>
1054 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.GreaterThan"/>
1055 /// 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.
1057 public static BinaryExpression GreaterThan(Expression left, Expression right, bool liftToNull, MethodInfo method) {
1058 RequiresCanRead(left, "left");
1059 RequiresCanRead(right, "right");
1060 if (method == null) {
1061 return GetComparisonOperator(ExpressionType.GreaterThan, "op_GreaterThan", left, right, liftToNull);
1063 return GetMethodBasedBinaryOperator(ExpressionType.GreaterThan, left, right, method, liftToNull);
1067 /// Creates a <see cref="BinaryExpression"/> that represents a "less than" numeric comparison.
1069 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1070 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1071 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.LessThan"/>
1072 /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
1074 public static BinaryExpression LessThan(Expression left, Expression right) {
1075 return LessThan(left, right, false, null);
1079 /// Creates a <see cref="BinaryExpression"/> that represents a "less than" numeric comparison.
1081 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1082 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1083 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
1084 /// <param name="liftToNull">true to set IsLiftedToNull to true; false to set IsLiftedToNull to false.</param>
1085 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.LessThan"/>
1086 /// 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.
1088 public static BinaryExpression LessThan(Expression left, Expression right, bool liftToNull, MethodInfo method) {
1089 RequiresCanRead(left, "left");
1090 RequiresCanRead(right, "right");
1091 if (method == null) {
1092 return GetComparisonOperator(ExpressionType.LessThan, "op_LessThan", left, right, liftToNull);
1094 return GetMethodBasedBinaryOperator(ExpressionType.LessThan, left, right, method, liftToNull);
1099 /// Creates a <see cref="BinaryExpression"/> that represents a "greater than or equal" numeric comparison.
1101 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1102 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1103 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.GreaterThanOrEqual"/>
1104 /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
1105 public static BinaryExpression GreaterThanOrEqual(Expression left, Expression right) {
1106 return GreaterThanOrEqual(left, right, false, null);
1110 /// Creates a <see cref="BinaryExpression"/> that represents a "greater than or equal" numeric comparison.
1112 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1113 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1114 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
1115 /// <param name="liftToNull">true to set IsLiftedToNull to true; false to set IsLiftedToNull to false.</param>
1116 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.GreaterThanOrEqual"/>
1117 /// 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.
1119 public static BinaryExpression GreaterThanOrEqual(Expression left, Expression right, bool liftToNull, MethodInfo method) {
1120 RequiresCanRead(left, "left");
1121 RequiresCanRead(right, "right");
1122 if (method == null) {
1123 return GetComparisonOperator(ExpressionType.GreaterThanOrEqual, "op_GreaterThanOrEqual", left, right, liftToNull);
1125 return GetMethodBasedBinaryOperator(ExpressionType.GreaterThanOrEqual, left, right, method, liftToNull);
1130 /// Creates a <see cref="BinaryExpression"/> that represents a "less than or equal" numeric comparison.
1132 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1133 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1134 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.LessThanOrEqual"/>
1135 /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
1136 public static BinaryExpression LessThanOrEqual(Expression left, Expression right) {
1137 return LessThanOrEqual(left, right, false, null);
1141 /// Creates a <see cref="BinaryExpression"/> that represents a "less than or equal" numeric comparison.
1143 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1144 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1145 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
1146 /// <param name="liftToNull">true to set IsLiftedToNull to true; false to set IsLiftedToNull to false.</param>
1147 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.LessThanOrEqual"/>
1148 /// 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.
1150 public static BinaryExpression LessThanOrEqual(Expression left, Expression right, bool liftToNull, MethodInfo method) {
1151 RequiresCanRead(left, "left");
1152 RequiresCanRead(right, "right");
1153 if (method == null) {
1154 return GetComparisonOperator(ExpressionType.LessThanOrEqual, "op_LessThanOrEqual", left, right, liftToNull);
1156 return GetMethodBasedBinaryOperator(ExpressionType.LessThanOrEqual, left, right, method, liftToNull);
1160 private static BinaryExpression GetComparisonOperator(ExpressionType binaryType, string opName, Expression left, Expression right, bool liftToNull) {
1161 if (left.Type == right.Type && TypeUtils.IsNumeric(left.Type)) {
1162 if (TypeUtils.IsNullableType(left.Type) && liftToNull) {
1163 return new SimpleBinaryExpression(binaryType, left, right, typeof(bool?));
1165 return new LogicalBinaryExpression(binaryType, left, right);
1168 return GetUserDefinedBinaryOperatorOrThrow(binaryType, opName, left, right, liftToNull);
1173 #region Boolean Expressions
1177 /// Creates a <see cref="BinaryExpression"/> that represents a conditional AND operation that evaluates the second operand only if it has to.
1179 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1180 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1181 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.AndAlso"/>
1182 /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
1183 public static BinaryExpression AndAlso(Expression left, Expression right) {
1184 return AndAlso(left, right, null);
1188 /// Creates a <see cref="BinaryExpression"/> that represents a conditional AND operation that evaluates the second operand only if it has to.
1190 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1191 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1192 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
1193 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.AndAlso"/>
1194 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
1196 public static BinaryExpression AndAlso(Expression left, Expression right, MethodInfo method) {
1197 RequiresCanRead(left, "left");
1198 RequiresCanRead(right, "right");
1200 if (method == null) {
1201 if (left.Type == right.Type) {
1202 if (left.Type == typeof(bool)) {
1203 return new LogicalBinaryExpression(ExpressionType.AndAlso, left, right);
1204 } else if (left.Type == typeof(bool?)) {
1205 return new SimpleBinaryExpression(ExpressionType.AndAlso, left, right, left.Type);
1208 method = GetUserDefinedBinaryOperator(ExpressionType.AndAlso, left.Type, right.Type, "op_BitwiseAnd");
1209 if (method != null) {
1210 ValidateUserDefinedConditionalLogicOperator(ExpressionType.AndAlso, left.Type, right.Type, method);
1211 returnType = (TypeUtils.IsNullableType(left.Type) && TypeUtils.AreEquivalent(method.ReturnType, TypeUtils.GetNonNullableType(left.Type))) ? left.Type : method.ReturnType;
1212 return new MethodBinaryExpression(ExpressionType.AndAlso, left, right, returnType, method);
1214 throw Error.BinaryOperatorNotDefined(ExpressionType.AndAlso, left.Type, right.Type);
1216 ValidateUserDefinedConditionalLogicOperator(ExpressionType.AndAlso, left.Type, right.Type, method);
1217 returnType = (TypeUtils.IsNullableType(left.Type) && TypeUtils.AreEquivalent(method.ReturnType, TypeUtils.GetNonNullableType(left.Type))) ? left.Type : method.ReturnType;
1218 return new MethodBinaryExpression(ExpressionType.AndAlso, left, right, returnType, method);
1223 /// Creates a <see cref="BinaryExpression"/> that represents a conditional OR operation that evaluates the second operand only if it has to.
1225 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1226 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1227 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.OrElse"/>
1228 /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
1229 public static BinaryExpression OrElse(Expression left, Expression right) {
1230 return OrElse(left, right, null);
1234 /// Creates a <see cref="BinaryExpression"/> that represents a conditional OR operation that evaluates the second operand only if it has to.
1236 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1237 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1238 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
1239 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.OrElse"/>
1240 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
1242 public static BinaryExpression OrElse(Expression left, Expression right, MethodInfo method) {
1243 RequiresCanRead(left, "left");
1244 RequiresCanRead(right, "right");
1246 if (method == null) {
1247 if (left.Type == right.Type) {
1248 if (left.Type == typeof(bool)) {
1249 return new LogicalBinaryExpression(ExpressionType.OrElse, left, right);
1250 } else if (left.Type == typeof(bool?)) {
1251 return new SimpleBinaryExpression(ExpressionType.OrElse, left, right, left.Type);
1254 method = GetUserDefinedBinaryOperator(ExpressionType.OrElse, left.Type, right.Type, "op_BitwiseOr");
1255 if (method != null) {
1256 ValidateUserDefinedConditionalLogicOperator(ExpressionType.OrElse, left.Type, right.Type, method);
1257 returnType = (TypeUtils.IsNullableType(left.Type) && method.ReturnType == TypeUtils.GetNonNullableType(left.Type)) ? left.Type : method.ReturnType;
1258 return new MethodBinaryExpression(ExpressionType.OrElse, left, right, returnType, method);
1260 throw Error.BinaryOperatorNotDefined(ExpressionType.OrElse, left.Type, right.Type);
1262 ValidateUserDefinedConditionalLogicOperator(ExpressionType.OrElse, left.Type, right.Type, method);
1263 returnType = (TypeUtils.IsNullableType(left.Type) && method.ReturnType == TypeUtils.GetNonNullableType(left.Type)) ? left.Type : method.ReturnType;
1264 return new MethodBinaryExpression(ExpressionType.OrElse, left, right, returnType, method);
1269 #region Coalescing Expressions
1273 /// Creates a BinaryExpression that represents a coalescing operation.
1275 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1276 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1277 /// <returns>A BinaryExpression that has the NodeType property equal to Coalesce and the Left and Right properties set to the specified values.</returns>
1278 public static BinaryExpression Coalesce(Expression left, Expression right) {
1279 return Coalesce(left, right, null);
1284 /// Creates a BinaryExpression that represents a coalescing operation.
1286 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1287 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1288 /// <param name="conversion">A LambdaExpression to set the Conversion property equal to.</param>
1289 /// <returns>A BinaryExpression that has the NodeType property equal to Coalesce and the Left, Right and Conversion properties set to the specified values.
1291 public static BinaryExpression Coalesce(Expression left, Expression right, LambdaExpression conversion) {
1292 RequiresCanRead(left, "left");
1293 RequiresCanRead(right, "right");
1295 if (conversion == null) {
1296 Type resultType = ValidateCoalesceArgTypes(left.Type, right.Type);
1297 return new SimpleBinaryExpression(ExpressionType.Coalesce, left, right, resultType);
1300 if (left.Type.IsValueType && !TypeUtils.IsNullableType(left.Type)) {
1301 throw Error.CoalesceUsedOnNonNullType();
1304 Type delegateType = conversion.Type;
1305 Debug.Assert(typeof(System.Delegate).IsAssignableFrom(delegateType) && delegateType != typeof(System.Delegate));
1306 MethodInfo method = delegateType.GetMethod("Invoke");
1307 if (method.ReturnType == typeof(void)) {
1308 throw Error.UserDefinedOperatorMustNotBeVoid(conversion);
1310 ParameterInfo[] pms = method.GetParametersCached();
1311 Debug.Assert(pms.Length == conversion.Parameters.Count);
1312 if (pms.Length != 1) {
1313 throw Error.IncorrectNumberOfMethodCallArguments(conversion);
1315 // The return type must match exactly.
1316 // CONSIDER: We could weaken this restriction and
1317 // CONSIDER: say that the return type must be assignable to from
1318 // CONSIDER: the return type of the lambda.
1319 if (!TypeUtils.AreEquivalent(method.ReturnType, right.Type)) {
1320 throw Error.OperandTypesDoNotMatchParameters(ExpressionType.Coalesce, conversion.ToString());
1322 // The parameter of the conversion lambda must either be assignable
1323 // from the erased or unerased type of the left hand side.
1324 if (!ParameterIsAssignable(pms[0], TypeUtils.GetNonNullableType(left.Type)) &&
1325 !ParameterIsAssignable(pms[0], left.Type)) {
1326 throw Error.OperandTypesDoNotMatchParameters(ExpressionType.Coalesce, conversion.ToString());
1328 return new CoalesceConversionBinaryExpression(left, right, conversion);
1332 private static Type ValidateCoalesceArgTypes(Type left, Type right) {
1333 Type leftStripped = TypeUtils.GetNonNullableType(left);
1334 if (left.IsValueType && !TypeUtils.IsNullableType(left)) {
1335 throw Error.CoalesceUsedOnNonNullType();
1336 } else if (TypeUtils.IsNullableType(left) && TypeUtils.IsImplicitlyConvertible(right, leftStripped)) {
1337 return leftStripped;
1338 } else if (TypeUtils.IsImplicitlyConvertible(right, left)) {
1340 } else if (TypeUtils.IsImplicitlyConvertible(leftStripped, right)) {
1343 throw Error.ArgumentTypesMustMatch();
1351 #region Arithmetic Expressions
1355 /// Creates a <see cref="BinaryExpression"/> that represents an arithmetic addition operation that does not have overflow checking.
1357 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1358 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1359 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.Add"/>
1360 /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
1361 public static BinaryExpression Add(Expression left, Expression right) {
1362 return Add(left, right, null);
1366 /// Creates a <see cref="BinaryExpression"/> that represents an arithmetic addition operation that does not have overflow checking.
1368 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1369 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1370 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
1371 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.Add"/>
1372 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
1374 public static BinaryExpression Add(Expression left, Expression right, MethodInfo method) {
1375 RequiresCanRead(left, "left");
1376 RequiresCanRead(right, "right");
1377 if (method == null) {
1378 if (left.Type == right.Type && TypeUtils.IsArithmetic(left.Type)) {
1379 return new SimpleBinaryExpression(ExpressionType.Add, left, right, left.Type);
1381 return GetUserDefinedBinaryOperatorOrThrow(ExpressionType.Add, "op_Addition", left, right, true);
1383 return GetMethodBasedBinaryOperator(ExpressionType.Add, left, right, method, true);
1388 /// Creates a <see cref="BinaryExpression"/> that represents an addition assignment operation that does not have overflow checking.
1390 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1391 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1392 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.AddAssign"/>
1393 /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
1394 public static BinaryExpression AddAssign(Expression left, Expression right) {
1395 return AddAssign(left, right, null, null);
1399 /// Creates a <see cref="BinaryExpression"/> that represents an addition assignment operation that does not have overflow checking.
1401 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1402 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1403 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
1404 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.AddAssign"/>
1405 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
1407 public static BinaryExpression AddAssign(Expression left, Expression right, MethodInfo method) {
1408 return AddAssign(left, right, method, null);
1412 /// Creates a <see cref="BinaryExpression"/> that represents an addition assignment operation that does not have overflow checking.
1414 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1415 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1416 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
1417 /// <param name="conversion">A <see cref="LambdaExpression"/> to set the <see cref="P:BinaryExpression.Conversion"/> property equal to.</param>
1418 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.AddAssign"/>
1419 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, <see cref="P:BinaryExpression.Method"/>,
1420 /// and <see cref="P:BinaryExpression.Conversion"/> properties set to the specified values.
1423 public static BinaryExpression AddAssign(Expression left, Expression right, MethodInfo method, LambdaExpression conversion) {
1424 RequiresCanRead(left, "left");
1425 RequiresCanWrite(left, "left");
1426 RequiresCanRead(right, "right");
1427 if (method == null) {
1428 if (left.Type == right.Type && TypeUtils.IsArithmetic(left.Type)) {
1429 // conversion is not supported for binary ops on arithmetic types without operator overloading
1430 if (conversion != null) {
1431 throw Error.ConversionIsNotSupportedForArithmeticTypes();
1433 return new SimpleBinaryExpression(ExpressionType.AddAssign, left, right, left.Type);
1435 return GetUserDefinedAssignOperatorOrThrow(ExpressionType.AddAssign, "op_Addition", left, right, conversion, true);
1437 return GetMethodBasedAssignOperator(ExpressionType.AddAssign, left, right, method, conversion, true);
1440 private static void ValidateOpAssignConversionLambda(LambdaExpression conversion, Expression left, MethodInfo method, ExpressionType nodeType) {
1441 Type delegateType = conversion.Type;
1442 Debug.Assert(typeof(System.Delegate).IsAssignableFrom(delegateType) && delegateType != typeof(System.Delegate));
1443 MethodInfo mi = delegateType.GetMethod("Invoke");
1444 ParameterInfo[] pms = mi.GetParametersCached();
1445 Debug.Assert(pms.Length == conversion.Parameters.Count);
1446 if (pms.Length != 1) {
1447 throw Error.IncorrectNumberOfMethodCallArguments(conversion);
1449 if (!TypeUtils.AreEquivalent(mi.ReturnType, left.Type)) {
1450 throw Error.OperandTypesDoNotMatchParameters(nodeType, conversion.ToString());
1452 if (method != null) {
1453 // The parameter type of conversion lambda must be the same as the return type of the overload method
1454 if (!TypeUtils.AreEquivalent(pms[0].ParameterType, method.ReturnType)) {
1455 throw Error.OverloadOperatorTypeDoesNotMatchConversionType(nodeType, conversion.ToString());
1462 /// Creates a <see cref="BinaryExpression"/> that represents an addition assignment operation that has overflow checking.
1464 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1465 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1466 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to
1467 /// <see cref="F:ExpressionType.AddAssignChecked"/> and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/>
1468 /// properties set to the specified values.
1470 public static BinaryExpression AddAssignChecked(Expression left, Expression right) {
1471 return AddAssignChecked(left, right, null);
1475 /// Creates a <see cref="BinaryExpression"/> that represents an addition assignment operation that has overflow checking.
1477 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1478 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1479 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
1480 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.AddAssignChecked"/>
1481 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
1483 public static BinaryExpression AddAssignChecked(Expression left, Expression right, MethodInfo method) {
1484 return AddAssignChecked(left, right, method, null);
1488 /// Creates a <see cref="BinaryExpression"/> that represents an addition assignment operation that has overflow checking.
1490 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1491 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1492 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
1493 /// <param name="conversion">A <see cref="LambdaExpression"/> to set the <see cref="P:BinaryExpression.Conversion"/> property equal to.</param>
1494 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.AddAssignChecked"/>
1495 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, <see cref="P:BinaryExpression.Method"/>,
1496 /// and <see cref="P:BinaryExpression.Conversion"/> properties set to the specified values.
1498 public static BinaryExpression AddAssignChecked(Expression left, Expression right, MethodInfo method, LambdaExpression conversion) {
1499 RequiresCanRead(left, "left");
1500 RequiresCanWrite(left, "left");
1501 RequiresCanRead(right, "right");
1503 if (method == null) {
1504 if (left.Type == right.Type && TypeUtils.IsArithmetic(left.Type)) {
1505 // conversion is not supported for binary ops on arithmetic types without operator overloading
1506 if (conversion != null) {
1507 throw Error.ConversionIsNotSupportedForArithmeticTypes();
1509 return new SimpleBinaryExpression(ExpressionType.AddAssignChecked, left, right, left.Type);
1511 return GetUserDefinedAssignOperatorOrThrow(ExpressionType.AddAssignChecked, "op_Addition", left, right, conversion, true);
1513 return GetMethodBasedAssignOperator(ExpressionType.AddAssignChecked, left, right, method, conversion, true);
1518 /// Creates a <see cref="BinaryExpression"/> that represents an arithmetic addition operation that has overflow checking.
1520 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1521 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> 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.AddChecked"/>
1523 /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
1524 public static BinaryExpression AddChecked(Expression left, Expression right) {
1525 return AddChecked(left, right, null);
1529 /// Creates a <see cref="BinaryExpression"/> that represents an arithmetic addition operation that has overflow checking.
1531 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1532 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1533 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
1534 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.AddChecked"/>
1535 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
1537 public static BinaryExpression AddChecked(Expression left, Expression right, MethodInfo method) {
1538 RequiresCanRead(left, "left");
1539 RequiresCanRead(right, "right");
1540 if (method == null) {
1541 if (left.Type == right.Type && TypeUtils.IsArithmetic(left.Type)) {
1542 return new SimpleBinaryExpression(ExpressionType.AddChecked, left, right, left.Type);
1544 return GetUserDefinedBinaryOperatorOrThrow(ExpressionType.AddChecked, "op_Addition", left, right, false);
1546 return GetMethodBasedBinaryOperator(ExpressionType.AddChecked, left, right, method, true);
1551 /// Creates a <see cref="BinaryExpression"/> that represents an arithmetic subtraction operation that does not have overflow checking.
1553 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1554 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1555 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.Subtract"/>
1556 /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
1557 public static BinaryExpression Subtract(Expression left, Expression right) {
1558 return Subtract(left, right, null);
1562 /// Creates a <see cref="BinaryExpression"/> that represents an arithmetic subtraction operation that does not have overflow checking.
1564 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1565 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1566 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
1567 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.Subtract"/>
1568 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
1570 public static BinaryExpression Subtract(Expression left, Expression right, MethodInfo method) {
1571 RequiresCanRead(left, "left");
1572 RequiresCanRead(right, "right");
1573 if (method == null) {
1574 if (left.Type == right.Type && TypeUtils.IsArithmetic(left.Type)) {
1575 return new SimpleBinaryExpression(ExpressionType.Subtract, left, right, left.Type);
1577 return GetUserDefinedBinaryOperatorOrThrow(ExpressionType.Subtract, "op_Subtraction", left, right, true);
1579 return GetMethodBasedBinaryOperator(ExpressionType.Subtract, left, right, method, true);
1584 /// Creates a <see cref="BinaryExpression"/> that represents a subtraction assignment operation that does not have overflow checking.
1586 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1587 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1588 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.SubtractAssign"/>
1589 /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
1590 public static BinaryExpression SubtractAssign(Expression left, Expression right) {
1591 return SubtractAssign(left, right, null, null);
1595 /// Creates a <see cref="BinaryExpression"/> that represents a subtraction assignment operation that does not have overflow checking.
1597 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1598 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1599 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
1600 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.SubtractAssign"/>
1601 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
1603 public static BinaryExpression SubtractAssign(Expression left, Expression right, MethodInfo method) {
1604 return SubtractAssign(left, right, method, null);
1608 /// Creates a <see cref="BinaryExpression"/> that represents a subtraction assignment operation that does not have overflow checking.
1610 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1611 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1612 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
1613 /// <param name="conversion">A <see cref="LambdaExpression"/> to set the <see cref="P:BinaryExpression.Conversion"/> property equal to.</param>
1614 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.SubtractAssign"/>
1615 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, <see cref="P:BinaryExpression.Method"/>,
1616 /// and <see cref="P:BinaryExpression.Conversion"/> properties set to the specified values.
1618 public static BinaryExpression SubtractAssign(Expression left, Expression right, MethodInfo method, LambdaExpression conversion) {
1619 RequiresCanRead(left, "left");
1620 RequiresCanWrite(left, "left");
1621 RequiresCanRead(right, "right");
1622 if (method == null) {
1623 if (left.Type == right.Type && TypeUtils.IsArithmetic(left.Type)) {
1624 // conversion is not supported for binary ops on arithmetic types without operator overloading
1625 if (conversion != null) {
1626 throw Error.ConversionIsNotSupportedForArithmeticTypes();
1628 return new SimpleBinaryExpression(ExpressionType.SubtractAssign, left, right, left.Type);
1630 return GetUserDefinedAssignOperatorOrThrow(ExpressionType.SubtractAssign, "op_Subtraction", left, right, conversion, true);
1632 return GetMethodBasedAssignOperator(ExpressionType.SubtractAssign, left, right, method, conversion, true);
1637 /// Creates a <see cref="BinaryExpression"/> that represents a subtraction assignment operation that has overflow checking.
1639 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1640 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1641 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.SubtractAssignChecked"/>
1642 /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
1643 public static BinaryExpression SubtractAssignChecked(Expression left, Expression right) {
1644 return SubtractAssignChecked(left, right, null);
1648 /// Creates a <see cref="BinaryExpression"/> that represents a subtraction assignment operation that has overflow checking.
1650 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1651 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1652 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
1653 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.SubtractAssignChecked"/>
1654 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
1656 public static BinaryExpression SubtractAssignChecked(Expression left, Expression right, MethodInfo method) {
1657 return SubtractAssignChecked(left, right, method, null);
1661 /// Creates a <see cref="BinaryExpression"/> that represents a subtraction assignment operation that has overflow checking.
1663 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1664 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1665 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
1666 /// <param name="conversion">A <see cref="LambdaExpression"/> to set the <see cref="P:BinaryExpression.Conversion"/> property equal to.</param>
1667 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.SubtractAssignChecked"/>
1668 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, <see cref="P:BinaryExpression.Method"/>,
1669 /// and <see cref="P:BinaryExpression.Conversion"/> properties set to the specified values.
1671 public static BinaryExpression SubtractAssignChecked(Expression left, Expression right, MethodInfo method, LambdaExpression conversion) {
1672 RequiresCanRead(left, "left");
1673 RequiresCanWrite(left, "left");
1674 RequiresCanRead(right, "right");
1675 if (method == null) {
1676 if (left.Type == right.Type && TypeUtils.IsArithmetic(left.Type)) {
1677 // conversion is not supported for binary ops on arithmetic types without operator overloading
1678 if (conversion != null) {
1679 throw Error.ConversionIsNotSupportedForArithmeticTypes();
1681 return new SimpleBinaryExpression(ExpressionType.SubtractAssignChecked, left, right, left.Type);
1683 return GetUserDefinedAssignOperatorOrThrow(ExpressionType.SubtractAssignChecked, "op_Subtraction", left, right, conversion, true);
1685 return GetMethodBasedAssignOperator(ExpressionType.SubtractAssignChecked, left, right, method, conversion, true);
1690 /// Creates a <see cref="BinaryExpression"/> that represents an arithmetic subtraction operation that has overflow checking.
1692 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1693 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1694 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.SubtractChecked"/>
1695 /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
1696 public static BinaryExpression SubtractChecked(Expression left, Expression right) {
1697 return SubtractChecked(left, right, null);
1701 /// Creates a <see cref="BinaryExpression"/> that represents an arithmetic subtraction operation that has overflow checking.
1703 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1704 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1705 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
1706 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.SubtractChecked"/>
1707 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
1709 public static BinaryExpression SubtractChecked(Expression left, Expression right, MethodInfo method) {
1710 RequiresCanRead(left, "left");
1711 RequiresCanRead(right, "right");
1712 if (method == null) {
1713 if (left.Type == right.Type && TypeUtils.IsArithmetic(left.Type)) {
1714 return new SimpleBinaryExpression(ExpressionType.SubtractChecked, left, right, left.Type);
1716 return GetUserDefinedBinaryOperatorOrThrow(ExpressionType.SubtractChecked, "op_Subtraction", left, right, true);
1718 return GetMethodBasedBinaryOperator(ExpressionType.SubtractChecked, left, right, method, true);
1723 /// Creates a <see cref="BinaryExpression"/> that represents an arithmetic division operation.
1725 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1726 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1727 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.Divide"/>
1728 /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
1729 public static BinaryExpression Divide(Expression left, Expression right) {
1730 return Divide(left, right, null);
1734 /// Creates a <see cref="BinaryExpression"/> that represents an arithmetic division operation.
1736 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1737 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1738 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
1739 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.Divide"/>
1740 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
1742 public static BinaryExpression Divide(Expression left, Expression right, MethodInfo method) {
1743 RequiresCanRead(left, "left");
1744 RequiresCanRead(right, "right");
1745 if (method == null) {
1746 if (left.Type == right.Type && TypeUtils.IsArithmetic(left.Type)) {
1747 return new SimpleBinaryExpression(ExpressionType.Divide, left, right, left.Type);
1749 return GetUserDefinedBinaryOperatorOrThrow(ExpressionType.Divide, "op_Division", left, right, true);
1751 return GetMethodBasedBinaryOperator(ExpressionType.Divide, left, right, method, true);
1756 /// Creates a <see cref="BinaryExpression"/> that represents a division assignment operation that does not have overflow checking.
1758 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1759 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1760 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.DivideAssign"/>
1761 /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
1762 public static BinaryExpression DivideAssign(Expression left, Expression right) {
1763 return DivideAssign(left, right, null, null);
1767 /// Creates a <see cref="BinaryExpression"/> that represents a division assignment operation that does not have overflow checking.
1769 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1770 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1771 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
1772 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.DivideAssign"/>
1773 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
1775 public static BinaryExpression DivideAssign(Expression left, Expression right, MethodInfo method) {
1776 return DivideAssign(left, right, method, null);
1780 /// Creates a <see cref="BinaryExpression"/> that represents a division assignment operation that does not have overflow checking.
1782 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1783 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1784 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
1785 /// <param name="conversion">A <see cref="LambdaExpression"/> to set the <see cref="P:BinaryExpression.Conversion"/> property equal to.</param>
1786 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.DivideAssign"/>
1787 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, <see cref="P:BinaryExpression.Method"/>,
1788 /// and <see cref="P:BinaryExpression.Conversion"/> properties set to the specified values.
1790 public static BinaryExpression DivideAssign(Expression left, Expression right, MethodInfo method, LambdaExpression conversion) {
1791 RequiresCanRead(left, "left");
1792 RequiresCanWrite(left, "left");
1793 RequiresCanRead(right, "right");
1794 if (method == null) {
1795 if (left.Type == right.Type && TypeUtils.IsArithmetic(left.Type)) {
1796 // conversion is not supported for binary ops on arithmetic types without operator overloading
1797 if (conversion != null) {
1798 throw Error.ConversionIsNotSupportedForArithmeticTypes();
1800 return new SimpleBinaryExpression(ExpressionType.DivideAssign, left, right, left.Type);
1802 return GetUserDefinedAssignOperatorOrThrow(ExpressionType.DivideAssign, "op_Division", left, right, conversion, true);
1804 return GetMethodBasedAssignOperator(ExpressionType.DivideAssign, left, right, method, conversion, true);
1809 /// Creates a <see cref="BinaryExpression"/> that represents an arithmetic remainder operation.
1811 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1812 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1813 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.Modulo"/>
1814 /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
1815 public static BinaryExpression Modulo(Expression left, Expression right) {
1816 return Modulo(left, right, null);
1820 /// Creates a <see cref="BinaryExpression"/> that represents an arithmetic remainder operation.
1822 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1823 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1824 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
1825 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.Modulo"/>
1826 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
1828 public static BinaryExpression Modulo(Expression left, Expression right, MethodInfo method) {
1829 RequiresCanRead(left, "left");
1830 RequiresCanRead(right, "right");
1831 if (method == null) {
1832 if (left.Type == right.Type && TypeUtils.IsArithmetic(left.Type)) {
1833 return new SimpleBinaryExpression(ExpressionType.Modulo, left, right, left.Type);
1835 return GetUserDefinedBinaryOperatorOrThrow(ExpressionType.Modulo, "op_Modulus", left, right, true);
1837 return GetMethodBasedBinaryOperator(ExpressionType.Modulo, left, right, method, true);
1842 /// Creates a <see cref="BinaryExpression"/> that represents a remainder assignment operation.
1844 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1845 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1846 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.ModuloAssign"/>
1847 /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
1848 public static BinaryExpression ModuloAssign(Expression left, Expression right) {
1849 return ModuloAssign(left, right, null, null);
1853 /// Creates a <see cref="BinaryExpression"/> that represents a remainder assignment operation.
1855 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1856 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1857 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
1858 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.ModuloAssign"/>
1859 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
1861 public static BinaryExpression ModuloAssign(Expression left, Expression right, MethodInfo method) {
1862 return ModuloAssign(left, right, method, null);
1866 /// Creates a <see cref="BinaryExpression"/> that represents a remainder assignment operation.
1868 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1869 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1870 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
1871 /// <param name="conversion">A <see cref="LambdaExpression"/> to set the <see cref="P:BinaryExpression.Conversion"/> property equal to.</param>
1872 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.ModuloAssign"/>
1873 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, <see cref="P:BinaryExpression.Method"/>,
1874 /// and <see cref="P:BinaryExpression.Conversion"/> properties set to the specified values.
1876 public static BinaryExpression ModuloAssign(Expression left, Expression right, MethodInfo method, LambdaExpression conversion) {
1877 RequiresCanRead(left, "left");
1878 RequiresCanWrite(left, "left");
1879 RequiresCanRead(right, "right");
1880 if (method == null) {
1881 if (left.Type == right.Type && TypeUtils.IsArithmetic(left.Type)) {
1882 // conversion is not supported for binary ops on arithmetic types without operator overloading
1883 if (conversion != null) {
1884 throw Error.ConversionIsNotSupportedForArithmeticTypes();
1886 return new SimpleBinaryExpression(ExpressionType.ModuloAssign, left, right, left.Type);
1888 return GetUserDefinedAssignOperatorOrThrow(ExpressionType.ModuloAssign, "op_Modulus", left, right, conversion, true);
1890 return GetMethodBasedAssignOperator(ExpressionType.ModuloAssign, left, right, method, conversion, true);
1895 /// Creates a <see cref="BinaryExpression"/> that represents an arithmetic multiplication operation that does not have overflow checking.
1897 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1898 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1899 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.Multiply"/>
1900 /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
1901 public static BinaryExpression Multiply(Expression left, Expression right) {
1902 return Multiply(left, right, null);
1906 /// Creates a <see cref="BinaryExpression"/> that represents an arithmetic multiplication operation that does not have overflow checking.
1908 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1909 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1910 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
1911 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.Multiply"/>
1912 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
1914 public static BinaryExpression Multiply(Expression left, Expression right, MethodInfo method) {
1915 RequiresCanRead(left, "left");
1916 RequiresCanRead(right, "right");
1917 if (method == null) {
1918 if (left.Type == right.Type && TypeUtils.IsArithmetic(left.Type)) {
1919 return new SimpleBinaryExpression(ExpressionType.Multiply, left, right, left.Type);
1921 return GetUserDefinedBinaryOperatorOrThrow(ExpressionType.Multiply, "op_Multiply", left, right, true);
1923 return GetMethodBasedBinaryOperator(ExpressionType.Multiply, left, right, method, true);
1928 /// Creates a <see cref="BinaryExpression"/> that represents a multiplication assignment operation that does not have overflow checking.
1930 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1931 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1932 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.MultiplyAssign"/>
1933 /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
1934 public static BinaryExpression MultiplyAssign(Expression left, Expression right) {
1935 return MultiplyAssign(left, right, null, null);
1939 /// Creates a <see cref="BinaryExpression"/> that represents a multiplication assignment operation that does not have overflow checking.
1941 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1942 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1943 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
1944 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.MultiplyAssign"/>
1945 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
1947 public static BinaryExpression MultiplyAssign(Expression left, Expression right, MethodInfo method) {
1948 return MultiplyAssign(left, right, method, null);
1952 /// Creates a <see cref="BinaryExpression"/> that represents a multiplication assignment operation that does not have overflow checking.
1954 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1955 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1956 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
1957 /// <param name="conversion">A <see cref="LambdaExpression"/> to set the <see cref="P:BinaryExpression.Conversion"/> property equal to.</param>
1958 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.MultiplyAssign"/>
1959 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, <see cref="P:BinaryExpression.Method"/>,
1960 /// and <see cref="P:BinaryExpression.Conversion"/> properties set to the specified values.
1962 public static BinaryExpression MultiplyAssign(Expression left, Expression right, MethodInfo method, LambdaExpression conversion) {
1963 RequiresCanRead(left, "left");
1964 RequiresCanWrite(left, "left");
1965 RequiresCanRead(right, "right");
1966 if (method == null) {
1967 if (left.Type == right.Type && TypeUtils.IsArithmetic(left.Type)) {
1968 // conversion is not supported for binary ops on arithmetic types without operator overloading
1969 if (conversion != null) {
1970 throw Error.ConversionIsNotSupportedForArithmeticTypes();
1972 return new SimpleBinaryExpression(ExpressionType.MultiplyAssign, left, right, left.Type);
1974 return GetUserDefinedAssignOperatorOrThrow(ExpressionType.MultiplyAssign, "op_Multiply", left, right, conversion, true);
1976 return GetMethodBasedAssignOperator(ExpressionType.MultiplyAssign, left, right, method, conversion, true);
1981 /// Creates a <see cref="BinaryExpression"/> that represents a multiplication assignment operation that has overflow checking.
1983 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1984 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1985 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.MultiplyAssignChecked"/>
1986 /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
1987 public static BinaryExpression MultiplyAssignChecked(Expression left, Expression right) {
1988 return MultiplyAssignChecked(left, right, null);
1992 /// Creates a <see cref="BinaryExpression"/> that represents a multiplication assignment operation that has overflow checking.
1994 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
1995 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
1996 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
1997 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.MultiplyAssignChecked"/>
1998 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
2000 public static BinaryExpression MultiplyAssignChecked(Expression left, Expression right, MethodInfo method) {
2001 return MultiplyAssignChecked(left, right, method, null);
2005 /// Creates a <see cref="BinaryExpression"/> that represents a multiplication assignment operation that has overflow checking.
2007 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
2008 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
2009 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
2010 /// <param name="conversion">A <see cref="LambdaExpression"/> to set the <see cref="P:BinaryExpression.Conversion"/> property equal to.</param>
2011 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.MultiplyAssignChecked"/>
2012 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, <see cref="P:BinaryExpression.Method"/>,
2013 /// and <see cref="P:BinaryExpression.Conversion"/> properties set to the specified values.
2015 public static BinaryExpression MultiplyAssignChecked(Expression left, Expression right, MethodInfo method, LambdaExpression conversion) {
2016 RequiresCanRead(left, "left");
2017 RequiresCanWrite(left, "left");
2018 RequiresCanRead(right, "right");
2019 if (method == null) {
2020 if (left.Type == right.Type && TypeUtils.IsArithmetic(left.Type)) {
2021 // conversion is not supported for binary ops on arithmetic types without operator overloading
2022 if (conversion != null) {
2023 throw Error.ConversionIsNotSupportedForArithmeticTypes();
2025 return new SimpleBinaryExpression(ExpressionType.MultiplyAssignChecked, left, right, left.Type);
2027 return GetUserDefinedAssignOperatorOrThrow(ExpressionType.MultiplyAssignChecked, "op_Multiply", left, right, conversion, true);
2029 return GetMethodBasedAssignOperator(ExpressionType.MultiplyAssignChecked, left, right, method, conversion, true);
2034 /// Creates a <see cref="BinaryExpression"/> that represents an arithmetic multiplication operation that has overflow checking.
2036 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
2037 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
2038 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.MultiplyChecked"/>
2039 /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
2040 public static BinaryExpression MultiplyChecked(Expression left, Expression right) {
2041 return MultiplyChecked(left, right, null);
2045 /// Creates a <see cref="BinaryExpression"/> that represents an arithmetic multiplication operation that has overflow checking.
2047 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
2048 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
2049 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
2050 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.MultiplyChecked"/>
2051 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
2053 public static BinaryExpression MultiplyChecked(Expression left, Expression right, MethodInfo method) {
2054 RequiresCanRead(left, "left");
2055 RequiresCanRead(right, "right");
2056 if (method == null) {
2057 if (left.Type == right.Type && TypeUtils.IsArithmetic(left.Type)) {
2058 return new SimpleBinaryExpression(ExpressionType.MultiplyChecked, left, right, left.Type);
2060 return GetUserDefinedBinaryOperatorOrThrow(ExpressionType.MultiplyChecked, "op_Multiply", left, right, true);
2062 return GetMethodBasedBinaryOperator(ExpressionType.MultiplyChecked, left, right, method, true);
2065 private static bool IsSimpleShift(Type left, Type right) {
2066 return TypeUtils.IsInteger(left)
2067 && TypeUtils.GetNonNullableType(right) == typeof(int);
2070 private static Type GetResultTypeOfShift(Type left, Type right) {
2071 if (!left.IsNullableType() && right.IsNullableType()) {
2072 // lift the result type to Nullable<T>
2073 return typeof(Nullable<>).MakeGenericType(left);
2080 /// Creates a <see cref="BinaryExpression"/> that represents an bitwise left-shift operation.
2082 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
2083 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
2084 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.LeftShift"/>
2085 /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
2086 public static BinaryExpression LeftShift(Expression left, Expression right) {
2087 return LeftShift(left, right, null);
2091 /// Creates a <see cref="BinaryExpression"/> that represents an bitwise left-shift operation.
2093 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
2094 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
2095 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
2096 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.LeftShift"/>
2097 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
2099 public static BinaryExpression LeftShift(Expression left, Expression right, MethodInfo method) {
2100 RequiresCanRead(left, "left");
2101 RequiresCanRead(right, "right");
2102 if (method == null) {
2103 if (IsSimpleShift(left.Type, right.Type)) {
2104 Type resultType = GetResultTypeOfShift(left.Type, right.Type);
2105 return new SimpleBinaryExpression(ExpressionType.LeftShift, left, right, resultType);
2107 return GetUserDefinedBinaryOperatorOrThrow(ExpressionType.LeftShift, "op_LeftShift", left, right, true);
2109 return GetMethodBasedBinaryOperator(ExpressionType.LeftShift, left, right, method, true);
2114 /// Creates a <see cref="BinaryExpression"/> that represents a bitwise left-shift assignment operation.
2116 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
2117 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
2118 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.LeftShiftAssign"/>
2119 /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
2120 public static BinaryExpression LeftShiftAssign(Expression left, Expression right) {
2121 return LeftShiftAssign(left, right, null, null);
2125 /// Creates a <see cref="BinaryExpression"/> that represents a bitwise left-shift assignment operation.
2127 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
2128 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
2129 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
2130 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.LeftShiftAssign"/>
2131 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
2133 public static BinaryExpression LeftShiftAssign(Expression left, Expression right, MethodInfo method) {
2134 return LeftShiftAssign(left, right, method, null);
2138 /// Creates a <see cref="BinaryExpression"/> that represents a bitwise left-shift assignment operation.
2140 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
2141 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
2142 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
2143 /// <param name="conversion">A <see cref="LambdaExpression"/> to set the <see cref="P:BinaryExpression.Conversion"/> property equal to.</param>
2144 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.LeftShiftAssign"/>
2145 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, <see cref="P:BinaryExpression.Method"/>,
2146 /// and <see cref="P:BinaryExpression.Conversion"/> properties set to the specified values.
2148 public static BinaryExpression LeftShiftAssign(Expression left, Expression right, MethodInfo method, LambdaExpression conversion) {
2149 RequiresCanRead(left, "left");
2150 RequiresCanWrite(left, "left");
2151 RequiresCanRead(right, "right");
2152 if (method == null) {
2153 if (IsSimpleShift(left.Type, right.Type)) {
2154 // conversion is not supported for binary ops on arithmetic types without operator overloading
2155 if (conversion != null) {
2156 throw Error.ConversionIsNotSupportedForArithmeticTypes();
2158 Type resultType = GetResultTypeOfShift(left.Type, right.Type);
2159 return new SimpleBinaryExpression(ExpressionType.LeftShiftAssign, left, right, resultType);
2161 return GetUserDefinedAssignOperatorOrThrow(ExpressionType.LeftShiftAssign, "op_LeftShift", left, right, conversion, true);
2163 return GetMethodBasedAssignOperator(ExpressionType.LeftShiftAssign, left, right, method, conversion, true);
2168 /// Creates a <see cref="BinaryExpression"/> that represents an bitwise right-shift operation.
2170 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
2171 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> 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.RightShift"/>
2173 /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
2174 public static BinaryExpression RightShift(Expression left, Expression right) {
2175 return RightShift(left, right, null);
2179 /// Creates a <see cref="BinaryExpression"/> that represents an bitwise right-shift operation.
2181 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
2182 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
2183 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
2184 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.RightShift"/>
2185 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
2187 public static BinaryExpression RightShift(Expression left, Expression right, MethodInfo method) {
2188 RequiresCanRead(left, "left");
2189 RequiresCanRead(right, "right");
2190 if (method == null) {
2191 if (IsSimpleShift(left.Type, right.Type)) {
2192 Type resultType = GetResultTypeOfShift(left.Type, right.Type);
2193 return new SimpleBinaryExpression(ExpressionType.RightShift, left, right, resultType);
2195 return GetUserDefinedBinaryOperatorOrThrow(ExpressionType.RightShift, "op_RightShift", left, right, true);
2197 return GetMethodBasedBinaryOperator(ExpressionType.RightShift, left, right, method, true);
2202 /// Creates a <see cref="BinaryExpression"/> that represents a bitwise right-shift assignment operation.
2204 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
2205 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
2206 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.RightShiftAssign"/>
2207 /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
2208 public static BinaryExpression RightShiftAssign(Expression left, Expression right) {
2209 return RightShiftAssign(left, right, null, null);
2213 /// Creates a <see cref="BinaryExpression"/> that represents a bitwise right-shift assignment operation.
2215 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
2216 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
2217 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
2218 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.RightShiftAssign"/>
2219 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
2221 public static BinaryExpression RightShiftAssign(Expression left, Expression right, MethodInfo method) {
2222 return RightShiftAssign(left, right, method, null);
2226 /// Creates a <see cref="BinaryExpression"/> that represents a bitwise right-shift assignment operation.
2228 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
2229 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
2230 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
2231 /// <param name="conversion">A <see cref="LambdaExpression"/> to set the <see cref="P:BinaryExpression.Conversion"/> property equal to.</param>
2232 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.RightShiftAssign"/>
2233 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, <see cref="P:BinaryExpression.Method"/>,
2234 /// and <see cref="P:BinaryExpression.Conversion"/> properties set to the specified values.
2236 public static BinaryExpression RightShiftAssign(Expression left, Expression right, MethodInfo method, LambdaExpression conversion) {
2237 RequiresCanRead(left, "left");
2238 RequiresCanWrite(left, "left");
2239 RequiresCanRead(right, "right");
2240 if (method == null) {
2241 if (IsSimpleShift(left.Type, right.Type)) {
2242 // conversion is not supported for binary ops on arithmetic types without operator overloading
2243 if (conversion != null) {
2244 throw Error.ConversionIsNotSupportedForArithmeticTypes();
2246 Type resultType = GetResultTypeOfShift(left.Type, right.Type);
2247 return new SimpleBinaryExpression(ExpressionType.RightShiftAssign, left, right, resultType);
2249 return GetUserDefinedAssignOperatorOrThrow(ExpressionType.RightShiftAssign, "op_RightShift", left, right, conversion, true);
2251 return GetMethodBasedAssignOperator(ExpressionType.RightShiftAssign, left, right, method, conversion, true);
2256 /// Creates a <see cref="BinaryExpression"/> that represents an bitwise AND operation.
2258 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
2259 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> 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.And"/>
2261 /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
2262 public static BinaryExpression And(Expression left, Expression right) {
2263 return And(left, right, null);
2267 /// Creates a <see cref="BinaryExpression"/> that represents an bitwise AND operation.
2269 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
2270 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
2271 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
2272 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.And"/>
2273 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
2275 public static BinaryExpression And(Expression left, Expression right, MethodInfo method) {
2276 RequiresCanRead(left, "left");
2277 RequiresCanRead(right, "right");
2278 if (method == null) {
2279 if (left.Type == right.Type && TypeUtils.IsIntegerOrBool(left.Type)) {
2280 return new SimpleBinaryExpression(ExpressionType.And, left, right, left.Type);
2282 return GetUserDefinedBinaryOperatorOrThrow(ExpressionType.And, "op_BitwiseAnd", left, right, true);
2284 return GetMethodBasedBinaryOperator(ExpressionType.And, left, right, method, true);
2289 /// Creates a <see cref="BinaryExpression"/> that represents a bitwise AND assignment operation.
2291 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
2292 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
2293 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.AndAssign"/>
2294 /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
2295 public static BinaryExpression AndAssign(Expression left, Expression right) {
2296 return AndAssign(left, right, null, null);
2300 /// Creates a <see cref="BinaryExpression"/> that represents a bitwise AND assignment operation.
2302 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
2303 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
2304 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
2305 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.AndAssign"/>
2306 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
2308 public static BinaryExpression AndAssign(Expression left, Expression right, MethodInfo method) {
2309 return AndAssign(left, right, method, null);
2313 /// Creates a <see cref="BinaryExpression"/> that represents a bitwise AND assignment operation.
2315 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
2316 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
2317 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
2318 /// <param name="conversion">A <see cref="LambdaExpression"/> to set the <see cref="P:BinaryExpression.Conversion"/> property equal to.</param>
2319 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.AndAssign"/>
2320 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, <see cref="P:BinaryExpression.Method"/>,
2321 /// and <see cref="P:BinaryExpression.Conversion"/> properties set to the specified values.
2323 public static BinaryExpression AndAssign(Expression left, Expression right, MethodInfo method, LambdaExpression conversion) {
2324 RequiresCanRead(left, "left");
2325 RequiresCanWrite(left, "left");
2326 RequiresCanRead(right, "right");
2327 if (method == null) {
2328 if (left.Type == right.Type && TypeUtils.IsIntegerOrBool(left.Type)) {
2329 // conversion is not supported for binary ops on arithmetic types without operator overloading
2330 if (conversion != null) {
2331 throw Error.ConversionIsNotSupportedForArithmeticTypes();
2333 return new SimpleBinaryExpression(ExpressionType.AndAssign, left, right, left.Type);
2335 return GetUserDefinedAssignOperatorOrThrow(ExpressionType.AndAssign, "op_BitwiseAnd", left, right, conversion, true);
2337 return GetMethodBasedAssignOperator(ExpressionType.AndAssign, left, right, method, conversion, true);
2342 /// Creates a <see cref="BinaryExpression"/> that represents an bitwise OR operation.
2344 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
2345 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
2346 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.Or"/>
2347 /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
2348 public static BinaryExpression Or(Expression left, Expression right) {
2349 return Or(left, right, null);
2353 /// Creates a <see cref="BinaryExpression"/> that represents an bitwise OR operation.
2355 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
2356 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
2357 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
2358 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.Or"/>
2359 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
2361 public static BinaryExpression Or(Expression left, Expression right, MethodInfo method) {
2362 RequiresCanRead(left, "left");
2363 RequiresCanRead(right, "right");
2364 if (method == null) {
2365 if (left.Type == right.Type && TypeUtils.IsIntegerOrBool(left.Type)) {
2366 return new SimpleBinaryExpression(ExpressionType.Or, left, right, left.Type);
2368 return GetUserDefinedBinaryOperatorOrThrow(ExpressionType.Or, "op_BitwiseOr", left, right, true);
2370 return GetMethodBasedBinaryOperator(ExpressionType.Or, left, right, method, true);
2375 /// Creates a <see cref="BinaryExpression"/> that represents a bitwise OR assignment operation.
2377 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
2378 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
2379 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.OrAssign"/>
2380 /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
2381 public static BinaryExpression OrAssign(Expression left, Expression right) {
2382 return OrAssign(left, right, null, null);
2386 /// Creates a <see cref="BinaryExpression"/> that represents a bitwise OR assignment operation.
2388 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
2389 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
2390 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
2391 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.OrAssign"/>
2392 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
2394 public static BinaryExpression OrAssign(Expression left, Expression right, MethodInfo method) {
2395 return OrAssign(left, right, method, null);
2399 /// Creates a <see cref="BinaryExpression"/> that represents a bitwise OR assignment operation.
2401 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
2402 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
2403 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
2404 /// <param name="conversion">A <see cref="LambdaExpression"/> to set the <see cref="P:BinaryExpression.Conversion"/> property equal to.</param>
2405 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.OrAssign"/>
2406 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, <see cref="P:BinaryExpression.Method"/>,
2407 /// and <see cref="P:BinaryExpression.Conversion"/> properties set to the specified values.
2409 public static BinaryExpression OrAssign(Expression left, Expression right, MethodInfo method, LambdaExpression conversion) {
2410 RequiresCanRead(left, "left");
2411 RequiresCanWrite(left, "left");
2412 RequiresCanRead(right, "right");
2413 if (method == null) {
2414 if (left.Type == right.Type && TypeUtils.IsIntegerOrBool(left.Type)) {
2415 // conversion is not supported for binary ops on arithmetic types without operator overloading
2416 if (conversion != null) {
2417 throw Error.ConversionIsNotSupportedForArithmeticTypes();
2419 return new SimpleBinaryExpression(ExpressionType.OrAssign, left, right, left.Type);
2421 return GetUserDefinedAssignOperatorOrThrow(ExpressionType.OrAssign, "op_BitwiseOr", left, right, conversion, true);
2423 return GetMethodBasedAssignOperator(ExpressionType.OrAssign, left, right, method, conversion, true);
2427 /// Creates a <see cref="BinaryExpression"/> that represents a bitwise or logical XOR operation, using op_ExclusiveOr for user-defined types.
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 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.ExclusiveOr"/>
2432 /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
2433 public static BinaryExpression ExclusiveOr(Expression left, Expression right) {
2434 return ExclusiveOr(left, right, null);
2438 /// Creates a <see cref="BinaryExpression"/> that represents a bitwise or logical XOR operation, using op_ExclusiveOr for user-defined types.
2440 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
2441 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
2442 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
2443 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.ExclusiveOr"/>
2444 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
2446 public static BinaryExpression ExclusiveOr(Expression left, Expression right, MethodInfo method) {
2447 RequiresCanRead(left, "left");
2448 RequiresCanRead(right, "right");
2449 if (method == null) {
2450 if (left.Type == right.Type && TypeUtils.IsIntegerOrBool(left.Type)) {
2451 return new SimpleBinaryExpression(ExpressionType.ExclusiveOr, left, right, left.Type);
2453 return GetUserDefinedBinaryOperatorOrThrow(ExpressionType.ExclusiveOr, "op_ExclusiveOr", left, right, true);
2455 return GetMethodBasedBinaryOperator(ExpressionType.ExclusiveOr, left, right, method, true);
2459 /// Creates a <see cref="BinaryExpression"/> that represents a bitwise or logical XOR assignment operation, using op_ExclusiveOr for user-defined types.
2461 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
2462 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
2463 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.ExclusiveOrAssign"/>
2464 /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
2465 public static BinaryExpression ExclusiveOrAssign(Expression left, Expression right) {
2466 return ExclusiveOrAssign(left, right, null, null);
2470 /// Creates a <see cref="BinaryExpression"/> that represents a bitwise or logical XOR assignment operation, using op_ExclusiveOr for user-defined types.
2472 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
2473 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
2474 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
2475 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.ExclusiveOrAssign"/>
2476 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
2478 public static BinaryExpression ExclusiveOrAssign(Expression left, Expression right, MethodInfo method) {
2479 return ExclusiveOrAssign(left, right, method, null);
2483 /// Creates a <see cref="BinaryExpression"/> that represents a bitwise or logical XOR assignment operation, using op_ExclusiveOr for user-defined types.
2485 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
2486 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
2487 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
2488 /// <param name="conversion">A <see cref="LambdaExpression"/> to set the <see cref="P:BinaryExpression.Conversion"/> property equal to.</param>
2489 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.ExclusiveOrAssign"/>
2490 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, <see cref="P:BinaryExpression.Method"/>,
2491 /// and <see cref="P:BinaryExpression.Conversion"/> properties set to the specified values.
2493 public static BinaryExpression ExclusiveOrAssign(Expression left, Expression right, MethodInfo method, LambdaExpression conversion) {
2494 RequiresCanRead(left, "left");
2495 RequiresCanWrite(left, "left");
2496 RequiresCanRead(right, "right");
2497 if (method == null) {
2498 if (left.Type == right.Type && TypeUtils.IsIntegerOrBool(left.Type)) {
2499 // conversion is not supported for binary ops on arithmetic types without operator overloading
2500 if (conversion != null) {
2501 throw Error.ConversionIsNotSupportedForArithmeticTypes();
2503 return new SimpleBinaryExpression(ExpressionType.ExclusiveOrAssign, left, right, left.Type);
2505 return GetUserDefinedAssignOperatorOrThrow(ExpressionType.ExclusiveOrAssign, "op_ExclusiveOr", left, right, conversion, true);
2507 return GetMethodBasedAssignOperator(ExpressionType.ExclusiveOrAssign, left, right, method, conversion, true);
2511 /// Creates a <see cref="BinaryExpression"/> that represents raising a number to a power.
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 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.Power"/>
2516 /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
2517 public static BinaryExpression Power(Expression left, Expression right) {
2518 return Power(left, right, null);
2522 /// Creates a <see cref="BinaryExpression"/> that represents raising a number to a power.
2524 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
2525 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
2526 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
2527 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.Power"/>
2528 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
2530 public static BinaryExpression Power(Expression left, Expression right, MethodInfo method) {
2531 RequiresCanRead(left, "left");
2532 RequiresCanRead(right, "right");
2533 if (method == null) {
2534 Type mathType = typeof(System.Math);
2535 method = mathType.GetMethod("Pow", BindingFlags.Static | BindingFlags.Public);
2536 if (method == null) {
2537 throw Error.BinaryOperatorNotDefined(ExpressionType.Power, left.Type, right.Type);
2540 return GetMethodBasedBinaryOperator(ExpressionType.Power, left, right, method, true);
2545 /// Creates a <see cref="BinaryExpression"/> that represents raising an expression to a power and assigning the result back to the expression.
2547 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
2548 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
2549 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.PowerAssign"/>
2550 /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
2551 public static BinaryExpression PowerAssign(Expression left, Expression right) {
2552 return PowerAssign(left, right, null, null);
2556 /// Creates a <see cref="BinaryExpression"/> that represents raising an expression to a power and assigning the result back to the expression.
2558 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
2559 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
2560 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
2561 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.PowerAssign"/>
2562 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
2564 public static BinaryExpression PowerAssign(Expression left, Expression right, MethodInfo method) {
2565 return PowerAssign(left, right, method, null);
2569 /// Creates a <see cref="BinaryExpression"/> that represents raising an expression to a power and assigning the result back to the expression.
2571 /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
2572 /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
2573 /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
2574 /// <param name="conversion">A <see cref="LambdaExpression"/> to set the <see cref="P:BinaryExpression.Conversion"/> property equal to.</param>
2575 /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.PowerAssign"/>
2576 /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, <see cref="P:BinaryExpression.Method"/>,
2577 /// and <see cref="P:BinaryExpression.Conversion"/> properties set to the specified values.
2579 public static BinaryExpression PowerAssign(Expression left, Expression right, MethodInfo method, LambdaExpression conversion) {
2580 RequiresCanRead(left, "left");
2581 RequiresCanWrite(left, "left");
2582 RequiresCanRead(right, "right");
2583 if (method == null) {
2584 Type mathType = typeof(System.Math);
2585 method = mathType.GetMethod("Pow", BindingFlags.Static | BindingFlags.Public);
2586 if (method == null) {
2587 throw Error.BinaryOperatorNotDefined(ExpressionType.PowerAssign, left.Type, right.Type);
2590 return GetMethodBasedAssignOperator(ExpressionType.PowerAssign, left, right, method, conversion, true);
2595 #region ArrayIndex Expression
2599 /// Creates a BinaryExpression that represents applying an array index operator to an array of rank one.
2601 /// <param name="array">An Expression to set the Left property equal to.</param>
2602 /// <param name="index">An Expression to set the Right property equal to.</param>
2603 /// <returns>A BinaryExpression that has the NodeType property equal to ArrayIndex and the Left and Right properties set to the specified values.</returns>
2604 public static BinaryExpression ArrayIndex(Expression array, Expression index) {
2605 RequiresCanRead(array, "array");
2606 RequiresCanRead(index, "index");
2607 if (index.Type != typeof(int)) {
2608 throw Error.ArgumentMustBeArrayIndexType();
2611 Type arrayType = array.Type;
2612 if (!arrayType.IsArray) {
2613 throw Error.ArgumentMustBeArray();
2615 if (arrayType.GetArrayRank() != 1) {
2616 throw Error.IncorrectNumberOfIndexes();
2619 return new SimpleBinaryExpression(ExpressionType.ArrayIndex, array, index, arrayType.GetElementType());