1 /* ****************************************************************************
3 * Copyright (c) Microsoft Corporation.
5 * This source code is subject to terms and conditions of the Microsoft Public License. A
6 * copy of the license can be found in the License.html file at the root of this distribution. If
7 * you cannot locate the Microsoft Public License, please send an email to
8 * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
9 * by the terms of the Microsoft Public License.
11 * You must not remove this notice, or any other, from this software.
14 * ***************************************************************************/
15 using System; using Microsoft;
18 using System.Diagnostics;
20 using System.Dynamic.Utils;
22 using Microsoft.Scripting.Utils;
24 using System.Reflection;
25 using System.Runtime.CompilerServices;
27 using Microsoft.Runtime.CompilerServices;
32 namespace System.Linq.Expressions {
34 namespace Microsoft.Linq.Expressions {
38 /// Represents an expression that has a unary operator.
41 [DebuggerTypeProxy(typeof(Expression.UnaryExpressionProxy))]
43 public sealed class UnaryExpression : Expression {
44 private readonly Expression _operand;
45 private readonly MethodInfo _method;
46 private readonly ExpressionType _nodeType;
47 private readonly Type _type;
49 internal UnaryExpression(ExpressionType nodeType, Expression expression, Type type, MethodInfo method) {
50 _operand = expression;
57 /// Gets the static type of the expression that this <see cref="Expression" /> represents. (Inherited from <see cref="Expression"/>.)
59 /// <returns>The <see cref="Type"/> that represents the static type of the expression.</returns>
60 public sealed override Type Type {
65 /// Returns the node type of this <see cref="Expression" />. (Inherited from <see cref="Expression" />.)
67 /// <returns>The <see cref="ExpressionType"/> that represents this expression.</returns>
68 public sealed override ExpressionType NodeType {
69 get { return _nodeType; }
73 /// Gets the operand of the unary operation.
75 /// <returns> An <see cref="ExpressionType"/> that represents the operand of the unary operation.</returns>
76 public Expression Operand {
77 get { return _operand; }
81 /// Gets the implementing method for the unary operation.
83 /// <returns>The <see cref="MethodInfo"/> that represents the implementing method.</returns>
84 public MethodInfo Method {
85 get { return _method; }
89 /// Gets a value that indicates whether the expression tree node represents a lifted call to an operator.
91 /// <returns>true if the node represents a lifted call; otherwise, false.</returns>
92 public bool IsLifted {
94 if (NodeType == ExpressionType.TypeAs || NodeType == ExpressionType.Quote || NodeType == ExpressionType.Throw) {
97 bool operandIsNullable = TypeUtils.IsNullableType(_operand.Type);
98 bool resultIsNullable = TypeUtils.IsNullableType(this.Type);
99 if (_method != null) {
100 return (operandIsNullable && !TypeUtils.AreEquivalent(_method.GetParametersCached()[0].ParameterType, _operand.Type)) ||
101 (resultIsNullable && !TypeUtils.AreEquivalent(_method.ReturnType, this.Type));
103 return operandIsNullable || resultIsNullable;
108 /// 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.
110 /// <returns>true if the operator's return type is lifted to a nullable type; otherwise, false.</returns>
111 public bool IsLiftedToNull {
113 return IsLifted && TypeUtils.IsNullableType(this.Type);
117 internal override Expression Accept(ExpressionVisitor visitor) {
118 return visitor.VisitUnary(this);
122 /// Gets a value that indicates whether the expression tree node can be reduced.
124 public override bool CanReduce {
127 case ExpressionType.PreIncrementAssign:
128 case ExpressionType.PreDecrementAssign:
129 case ExpressionType.PostIncrementAssign:
130 case ExpressionType.PostDecrementAssign:
138 /// Reduces the expression node to a simpler expression.
139 /// If CanReduce returns true, this should return a valid expression.
140 /// This method is allowed to return another node which itself
143 /// <returns>The reduced expression.</returns>
144 public override Expression Reduce() {
146 switch (_operand.NodeType) {
147 case ExpressionType.Index:
148 return ReduceIndex();
149 case ExpressionType.MemberAccess:
150 return ReduceMember();
152 return ReduceVariable();
158 private bool IsPrefix {
159 get { return _nodeType == ExpressionType.PreIncrementAssign || _nodeType == ExpressionType.PreDecrementAssign; }
162 private UnaryExpression FunctionalOp(Expression operand) {
163 ExpressionType functional;
164 if (_nodeType == ExpressionType.PreIncrementAssign || _nodeType == ExpressionType.PostIncrementAssign) {
165 functional = ExpressionType.Increment;
167 functional = ExpressionType.Decrement;
169 return new UnaryExpression(functional, operand, operand.Type, _method);
172 private Expression ReduceVariable() {
175 // ... is reduced into ...
177 return Assign(_operand, FunctionalOp(_operand));
180 // ... is reduced into ...
184 var temp = Parameter(_operand.Type, null);
187 Assign(temp, _operand),
188 Assign(_operand, FunctionalOp(temp)),
193 private Expression ReduceMember() {
194 var member = (MemberExpression)_operand;
195 if (member.Expression == null) {
196 //static member, reduce the same as variable
197 return ReduceVariable();
199 var temp1 = Parameter(member.Expression.Type, null);
200 var initTemp1 = Assign(temp1, member.Expression);
201 member = MakeMemberAccess(temp1, member.Member);
205 // ... is reduced into ...
207 // temp1.member = op(temp1.member)
211 Assign(member, FunctionalOp(member))
216 // ... is reduced into ...
218 // temp2 = temp1.member
219 // temp1.member = op(temp2)
221 var temp2 = Parameter(member.Type, null);
223 new[] { temp1, temp2 },
225 Assign(temp2, member),
226 Assign(member, FunctionalOp(temp2)),
232 private Expression ReduceIndex() {
233 // left[a0, a1, ... aN] (op)
235 // ... is reduced into ...
241 // tempValue = tempObj[tempArg0, ... tempArgN]
242 // tempObj[tempArg0, ... tempArgN] = op(tempValue)
245 bool prefix = IsPrefix;
246 var index = (IndexExpression)_operand;
247 int count = index.Arguments.Count;
248 var block = new Expression[count + (prefix ? 2 : 4)];
249 var temps = new ParameterExpression[count + (prefix ? 1 : 2)];
250 var args = new ParameterExpression[count];
253 temps[i] = Parameter(index.Object.Type, null);
254 block[i] = Assign(temps[i], index.Object);
257 var arg = index.Arguments[i - 1];
258 args[i - 1] = temps[i] = Parameter(arg.Type, null);
259 block[i] = Assign(temps[i], arg);
262 index = MakeIndex(temps[0], index.Indexer, new TrueReadOnlyCollection<Expression>(args));
264 var lastTemp = temps[i] = Parameter(index.Type, null);
265 block[i] = Assign(temps[i], index);
267 Debug.Assert(i == temps.Length);
268 block[i++] = Assign(index, FunctionalOp(lastTemp));
269 block[i++] = lastTemp;
271 Debug.Assert(i == temps.Length);
272 block[i++] = Assign(index, FunctionalOp(index));
274 Debug.Assert(i == block.Length);
275 return Block(new TrueReadOnlyCollection<ParameterExpression>(temps), new TrueReadOnlyCollection<Expression>(block));
279 public partial class Expression {
282 /// Creates a <see cref="UnaryExpression"></see>, given an operand, by calling the appropriate factory method.
284 /// <param name="unaryType">The <see cref="ExpressionType"></see> that specifies the type of unary operation.</param>
285 /// <param name="operand">An <see cref="Expression"></see> that represents the operand.</param>
286 /// <param name="type">The <see cref="Type"></see> that specifies the type to be converted to (pass null if not applicable).</param>
287 /// <returns>The <see cref="UnaryExpression"></see> that results from calling the appropriate factory method.</returns>
288 /// <exception cref="ArgumentException">Thrown when <paramref name="unaryType"/> does not correspond to a unary expression.</exception>
289 /// <exception cref="ArgumentNullException">Thrown when <paramref name="operand"/> is null.</exception>
290 public static UnaryExpression MakeUnary(ExpressionType unaryType, Expression operand, Type type) {
291 return MakeUnary(unaryType, operand, type, null);
295 /// Creates a <see cref="UnaryExpression"></see>, given an operand and implementing method, by calling the appropriate factory method.
297 /// <param name="unaryType">The <see cref="ExpressionType"></see> that specifies the type of unary operation.</param>
298 /// <param name="operand">An <see cref="Expression"></see> that represents the operand.</param>
299 /// <param name="type">The <see cref="Type"></see> that specifies the type to be converted to (pass null if not applicable).</param>
300 /// <param name="method">The <see cref="MethodInfo"></see> that represents the implementing method.</param>
301 /// <returns>The <see cref="UnaryExpression"></see> that results from calling the appropriate factory method.</returns>
302 /// <exception cref="ArgumentException">Thrown when <paramref name="unaryType"/> does not correspond to a unary expression.</exception>
303 /// <exception cref="ArgumentNullException">Thrown when <paramref name="operand"/> is null.</exception>
304 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
305 public static UnaryExpression MakeUnary(ExpressionType unaryType, Expression operand, Type type, MethodInfo method) {
307 case ExpressionType.Negate:
308 return Negate(operand, method);
309 case ExpressionType.NegateChecked:
310 return NegateChecked(operand, method);
311 case ExpressionType.Not:
312 return Not(operand, method);
313 case ExpressionType.IsFalse:
314 return IsFalse(operand, method);
315 case ExpressionType.IsTrue:
316 return IsTrue(operand, method);
317 case ExpressionType.OnesComplement:
318 return OnesComplement(operand, method);
319 case ExpressionType.ArrayLength:
320 return ArrayLength(operand);
321 case ExpressionType.Convert:
322 return Convert(operand, type, method);
323 case ExpressionType.ConvertChecked:
324 return ConvertChecked(operand, type, method);
325 case ExpressionType.Throw:
326 return Throw(operand, type);
327 case ExpressionType.TypeAs:
328 return TypeAs(operand, type);
329 case ExpressionType.Quote:
330 return Quote(operand);
331 case ExpressionType.UnaryPlus:
332 return UnaryPlus(operand, method);
333 case ExpressionType.Unbox:
334 return Unbox(operand, type);
335 case ExpressionType.Increment:
336 return Increment(operand, method);
337 case ExpressionType.Decrement:
338 return Decrement(operand, method);
339 case ExpressionType.PreIncrementAssign:
340 return PreIncrementAssign(operand, method);
341 case ExpressionType.PostIncrementAssign:
342 return PostIncrementAssign(operand, method);
343 case ExpressionType.PreDecrementAssign:
344 return PreDecrementAssign(operand, method);
345 case ExpressionType.PostDecrementAssign:
346 return PostDecrementAssign(operand, method);
348 throw Error.UnhandledUnary(unaryType);
352 private static UnaryExpression GetUserDefinedUnaryOperatorOrThrow(ExpressionType unaryType, string name, Expression operand) {
353 UnaryExpression u = GetUserDefinedUnaryOperator(unaryType, name, operand);
355 ValidateParamswithOperandsOrThrow(u.Method.GetParametersCached()[0].ParameterType, operand.Type, unaryType, name);
358 throw Error.UnaryOperatorNotDefined(unaryType, operand.Type);
361 private static UnaryExpression GetUserDefinedUnaryOperator(ExpressionType unaryType, string name, Expression operand) {
362 Type operandType = operand.Type;
363 Type[] types = new Type[] { operandType };
364 Type nnOperandType = TypeUtils.GetNonNullableType(operandType);
365 BindingFlags flags = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
366 MethodInfo method = nnOperandType.GetMethodValidated(name, flags, null, types, null);
367 if (method != null) {
368 return new UnaryExpression(unaryType, operand, method.ReturnType, method);
371 if (TypeUtils.IsNullableType(operandType)) {
372 types[0] = nnOperandType;
373 method = nnOperandType.GetMethodValidated(name, flags, null, types, null);
374 if (method != null && method.ReturnType.IsValueType && !TypeUtils.IsNullableType(method.ReturnType)) {
375 return new UnaryExpression(unaryType, operand, TypeUtils.GetNullableType(method.ReturnType), method);
381 private static UnaryExpression GetMethodBasedUnaryOperator(ExpressionType unaryType, Expression operand, MethodInfo method) {
382 System.Diagnostics.Debug.Assert(method != null);
383 ValidateOperator(method);
384 ParameterInfo[] pms = method.GetParametersCached();
386 throw Error.IncorrectNumberOfMethodCallArguments(method);
387 if (ParameterIsAssignable(pms[0], operand.Type)) {
388 ValidateParamswithOperandsOrThrow(pms[0].ParameterType, operand.Type, unaryType, method.Name);
389 return new UnaryExpression(unaryType, operand, method.ReturnType, method);
391 // check for lifted call
392 if (TypeUtils.IsNullableType(operand.Type) &&
393 ParameterIsAssignable(pms[0], TypeUtils.GetNonNullableType(operand.Type)) &&
394 method.ReturnType.IsValueType && !TypeUtils.IsNullableType(method.ReturnType)) {
395 return new UnaryExpression(unaryType, operand, TypeUtils.GetNullableType(method.ReturnType), method);
398 throw Error.OperandTypesDoNotMatchParameters(unaryType, method.Name);
401 private static UnaryExpression GetUserDefinedCoercionOrThrow(ExpressionType coercionType, Expression expression, Type convertToType) {
402 UnaryExpression u = GetUserDefinedCoercion(coercionType, expression, convertToType);
406 throw Error.CoercionOperatorNotDefined(expression.Type, convertToType);
409 private static UnaryExpression GetUserDefinedCoercion(ExpressionType coercionType, Expression expression, Type convertToType) {
410 MethodInfo method = TypeUtils.GetUserDefinedCoercionMethod(expression.Type, convertToType, false);
411 if (method != null) {
412 return new UnaryExpression(coercionType, expression, convertToType, method);
418 private static UnaryExpression GetMethodBasedCoercionOperator(ExpressionType unaryType, Expression operand, Type convertToType, MethodInfo method) {
419 System.Diagnostics.Debug.Assert(method != null);
420 ValidateOperator(method);
421 ParameterInfo[] pms = method.GetParametersCached();
422 if (pms.Length != 1) {
423 throw Error.IncorrectNumberOfMethodCallArguments(method);
425 if (ParameterIsAssignable(pms[0], operand.Type) && TypeUtils.AreEquivalent(method.ReturnType, convertToType)) {
426 return new UnaryExpression(unaryType, operand, method.ReturnType, method);
428 // check for lifted call
429 if ((TypeUtils.IsNullableType(operand.Type) || TypeUtils.IsNullableType(convertToType)) &&
430 ParameterIsAssignable(pms[0], TypeUtils.GetNonNullableType(operand.Type)) &&
431 TypeUtils.AreEquivalent(method.ReturnType, TypeUtils.GetNonNullableType(convertToType))) {
432 return new UnaryExpression(unaryType, operand, convertToType, method);
434 throw Error.OperandTypesDoNotMatchParameters(unaryType, method.Name);
438 /// Creates a <see cref="UnaryExpression"></see> that represents an arithmetic negation operation.
440 /// <param name="expression">An <see cref="Expression"></see> to set the <see cref="P:UnaryExpression.Operand"></see> property equal to.</param>
441 /// <returns>A <see cref="UnaryExpression"></see> that has the <see cref="P:Expression.NodeType"></see> property equal to <see cref="P:ExpressionType.Negate"></see> and the <see cref="P:UnaryExpression.Operand"></see> properties set to the specified value.</returns>
442 /// <exception cref="ArgumentNullException">Thrown when <paramref name="expression"/> is null.</exception>
443 /// <exception cref="InvalidOperationException">Thrown when the unary minus operator is not defined for <see cref="P:Expression.Type"></see></exception>
444 public static UnaryExpression Negate(Expression expression) {
445 return Negate(expression, null);
449 /// Creates a <see cref="UnaryExpression"></see> that represents an arithmetic negation operation.
451 /// <param name="expression">An <see cref="Expression"></see> to set the <see cref="P:UnaryExpression.Operand"></see> property equal to.</param>
452 /// <param name="method">A <see cref="MethodInfo"></see> to set the <see cref="P:UnaryExpression.Method"></see> property equal to.</param>
453 /// <returns>A <see cref="UnaryExpression"></see> that has the <see cref="P:Expression.NodeType"></see> property equal to <see cref="P:ExpressionType.Negate"></see> and the <see cref="P:UnaryExpression.Operand"></see> and <see cref="P:UnaryExpression.Method"></see> properties set to the specified value.</returns>
454 /// <exception cref="ArgumentNullException">Thrown when <paramref name="expression"/> is null.</exception>
455 /// <exception cref="ArgumentException">Thrown when <paramref name="method"/> is not null and the method it represents returns void, is not static (Shared in Visual Basic), or does not take exactly one argument.</exception>
456 /// <exception cref="InvalidOperationException">Thown when <paramref name="method"/> is null and the unary minus operator is not defined for expression.Type or expression.Type (or its corresponding non-nullable type if it is a nullable value type) is not assignable to the argument type of the method represented by method.</exception>
457 public static UnaryExpression Negate(Expression expression, MethodInfo method) {
458 RequiresCanRead(expression, "expression");
459 if (method == null) {
460 if (TypeUtils.IsArithmetic(expression.Type) && !TypeUtils.IsUnsignedInt(expression.Type)) {
461 return new UnaryExpression(ExpressionType.Negate, expression, expression.Type, null);
463 return GetUserDefinedUnaryOperatorOrThrow(ExpressionType.Negate, "op_UnaryNegation", expression);
465 return GetMethodBasedUnaryOperator(ExpressionType.Negate, expression, method);
469 /// Creates a <see cref="UnaryExpression"></see> that represents a unary plus operation.
471 /// <param name="expression">An <see cref="Expression"></see> to set the <see cref="UnaryExpression.Operand"></see> property equal to.</param>
472 /// <returns>A <see cref="UnaryExpression"></see> that has the <see cref="Expression.NodeType"></see> property equal to <see cref="ExpressionType.UnaryPlus"></see> and the <see cref="UnaryExpression.Operand"></see> property set to the specified value.</returns>
473 /// <exception cref="ArgumentNullException">Thrown when <paramref name="expression"/> is null.</exception>
474 /// <exception cref="InvalidOperationException">Thown when the unary minus operator is not defined for expression.Type.</exception>
475 public static UnaryExpression UnaryPlus(Expression expression) {
476 return UnaryPlus(expression, null);
480 /// Creates a <see cref="UnaryExpression"></see> that represents a unary plus operation.
482 /// <param name="expression">An <see cref="Expression"></see> to set the <see cref="UnaryExpression.Operand"></see> property equal to.</param>
483 /// <param name="method">A <see cref="MethodInfo"></see> to set the <see cref="UnaryExpression.Method"></see> property equal to.</param>
484 /// <returns>A <see cref="UnaryExpression"></see> that has the <see cref="Expression.NodeType"></see> property equal to <see cref="ExpressionType.UnaryPlus"></see> and the <see cref="UnaryExpression.Operand"></see> and <see cref="UnaryExpression.Method"></see>property set to the specified value.</returns>
485 /// <exception cref="ArgumentNullException">Thrown when <paramref name="expression"/> is null.</exception>
486 /// <exception cref="ArgumentException">Thrown when <paramref name="method"/> is not null and the method it represents returns void, is not static (Shared in Visual Basic), or does not take exactly one argument.</exception>
487 /// <exception cref="InvalidOperationException">Thown when <paramref name="method"/> is null and the unary minus operator is not defined for expression.Type or expression.Type (or its corresponding non-nullable type if it is a nullable value type) is not assignable to the argument type of the method represented by method.</exception>
488 public static UnaryExpression UnaryPlus(Expression expression, MethodInfo method) {
489 RequiresCanRead(expression, "expression");
490 if (method == null) {
491 if (TypeUtils.IsArithmetic(expression.Type)) {
492 return new UnaryExpression(ExpressionType.UnaryPlus, expression, expression.Type, null);
494 return GetUserDefinedUnaryOperatorOrThrow(ExpressionType.UnaryPlus, "op_UnaryPlus", expression);
496 return GetMethodBasedUnaryOperator(ExpressionType.UnaryPlus, expression, method);
499 /// <summary>Creates a <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that represents an arithmetic negation operation that has overflow checking.</summary>
500 /// <returns>A <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that has the <see cref="P:Microsoft.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:Microsoft.Linq.Expressions.ExpressionType.NegateChecked" /> and the <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Operand" /> property set to the specified value.</returns>
501 /// <param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression" /> to set the <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Operand" /> property equal to.</param>
502 /// <exception cref="T:System.ArgumentNullException">
503 /// Thrown when <paramref name="expression" /> is null.</exception>
504 /// <exception cref="T:System.InvalidOperationException">Thrown when the unary minus operator is not defined for <paramref name="expression" />.Type.</exception>
505 public static UnaryExpression NegateChecked(Expression expression) {
506 return NegateChecked(expression, null);
509 ///<summary>Creates a <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that represents an arithmetic negation operation that has overflow checking. The implementing method can be specified.</summary>
510 ///<returns>A <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that has the <see cref="P:Microsoft.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:Microsoft.Linq.Expressions.ExpressionType.NegateChecked" /> and the <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Operand" /> and <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Method" /> properties set to the specified values.</returns>
511 ///<param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression" /> to set the <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Operand" /> property equal to.</param>
512 ///<param name="method">A <see cref="T:System.Reflection.MethodInfo" /> to set the <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Method" /> property equal to.</param>
513 ///<exception cref="T:System.ArgumentNullException">
514 ///<paramref name="expression" /> is null.</exception>
515 ///<exception cref="T:System.ArgumentException">
516 ///<paramref name="method" /> is not null and the method it represents returns void, is not static (Shared in Visual Basic), or does not take exactly one argument.</exception>
517 ///<exception cref="T:System.InvalidOperationException">
518 ///<paramref name="method" /> is null and the unary minus operator is not defined for <paramref name="expression" />.Type.-or-<paramref name="expression" />.Type (or its corresponding non-nullable type if it is a nullable value type) is not assignable to the argument type of the method represented by <paramref name="method" />.</exception>
519 public static UnaryExpression NegateChecked(Expression expression, MethodInfo method) {
520 RequiresCanRead(expression, "expression");
521 if (method == null) {
522 if (TypeUtils.IsArithmetic(expression.Type) && !TypeUtils.IsUnsignedInt(expression.Type)) {
523 return new UnaryExpression(ExpressionType.NegateChecked, expression, expression.Type, null);
525 return GetUserDefinedUnaryOperatorOrThrow(ExpressionType.NegateChecked, "op_UnaryNegation", expression);
527 return GetMethodBasedUnaryOperator(ExpressionType.NegateChecked, expression, method);
530 ///<summary>Creates a <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that represents a bitwise complement operation.</summary>
531 ///<returns>A <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that has the <see cref="P:Microsoft.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:Microsoft.Linq.Expressions.ExpressionType.Not" /> and the <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Operand" /> property set to the specified value.</returns>
532 ///<param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression" /> to set the <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Operand" /> property equal to.</param>
533 ///<exception cref="T:System.ArgumentNullException">
534 ///<paramref name="expression" /> is null.</exception>
535 ///<exception cref="T:System.InvalidOperationException">The unary not operator is not defined for <paramref name="expression" />.Type.</exception>
536 public static UnaryExpression Not(Expression expression) {
537 return Not(expression, null);
540 ///<summary>Creates a <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that represents a bitwise complement operation. The implementing method can be specified.</summary>
541 ///<returns>A <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that has the <see cref="P:Microsoft.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:Microsoft.Linq.Expressions.ExpressionType.Not" /> and the <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Operand" /> and <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Method" /> properties set to the specified values.</returns>
542 ///<param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression" /> to set the <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Operand" /> property equal to.</param>
543 ///<param name="method">A <see cref="T:System.Reflection.MethodInfo" /> to set the <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Method" /> property equal to.</param>
544 ///<exception cref="T:System.ArgumentNullException">
545 ///<paramref name="expression" /> is null.</exception>
546 ///<exception cref="T:System.ArgumentException">
547 ///<paramref name="method" /> is not null and the method it represents returns void, is not static (Shared in Visual Basic), or does not take exactly one argument.</exception>
548 ///<exception cref="T:System.InvalidOperationException">
549 ///<paramref name="method" /> is null and the unary not operator is not defined for <paramref name="expression" />.Type.-or-<paramref name="expression" />.Type (or its corresponding non-nullable type if it is a nullable value type) is not assignable to the argument type of the method represented by <paramref name="method" />.</exception>
550 public static UnaryExpression Not(Expression expression, MethodInfo method) {
551 RequiresCanRead(expression, "expression");
552 if (method == null) {
553 if (TypeUtils.IsIntegerOrBool(expression.Type)) {
554 return new UnaryExpression(ExpressionType.Not, expression, expression.Type, null);
556 UnaryExpression u = GetUserDefinedUnaryOperator(ExpressionType.Not, "op_LogicalNot", expression);
560 return GetUserDefinedUnaryOperatorOrThrow(ExpressionType.Not, "op_OnesComplement", expression);
562 return GetMethodBasedUnaryOperator(ExpressionType.Not, expression, method);
566 /// Returns whether the expression evaluates to false.
568 /// <param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression" /> to evaluate.</param>
569 /// <returns>An instance of <see cref="UnaryExpression"/>.</returns>
570 public static UnaryExpression IsFalse(Expression expression) {
571 return IsFalse(expression, null);
575 /// Returns whether the expression evaluates to false.
577 ///<param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression" /> to evaluate.</param>
578 ///<param name="method">A <see cref="T:System.Reflection.MethodInfo" /> that represents the implementing method.</param>
579 /// <returns>An instance of <see cref="UnaryExpression"/>.</returns>
580 public static UnaryExpression IsFalse(Expression expression, MethodInfo method) {
581 RequiresCanRead(expression, "expression");
582 if (method == null) {
583 if (TypeUtils.IsBool(expression.Type)) {
584 return new UnaryExpression(ExpressionType.IsFalse, expression, expression.Type, null);
586 return GetUserDefinedUnaryOperatorOrThrow(ExpressionType.IsFalse, "op_False", expression);
588 return GetMethodBasedUnaryOperator(ExpressionType.IsFalse, expression, method);
592 /// Returns whether the expression evaluates to true.
594 /// <param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression" /> to evaluate.</param>
595 /// <returns>An instance of <see cref="UnaryExpression"/>.</returns>
596 public static UnaryExpression IsTrue(Expression expression) {
597 return IsTrue(expression, null);
601 /// Returns whether the expression evaluates to true.
603 ///<param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression" /> to evaluate.</param>
604 ///<param name="method">A <see cref="T:System.Reflection.MethodInfo" /> that represents the implementing method.</param>
605 /// <returns>An instance of <see cref="UnaryExpression"/>.</returns>
606 public static UnaryExpression IsTrue(Expression expression, MethodInfo method) {
607 RequiresCanRead(expression, "expression");
608 if (method == null) {
609 if (TypeUtils.IsBool(expression.Type)) {
610 return new UnaryExpression(ExpressionType.IsTrue, expression, expression.Type, null);
612 return GetUserDefinedUnaryOperatorOrThrow(ExpressionType.IsTrue, "op_True", expression);
614 return GetMethodBasedUnaryOperator(ExpressionType.IsTrue, expression, method);
618 /// Returns the expression representing the ones complement.
620 ///<param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression" />.</param>
621 /// <returns>An instance of <see cref="UnaryExpression"/>.</returns>
622 public static UnaryExpression OnesComplement(Expression expression) {
623 return OnesComplement(expression, null);
627 /// Returns the expression representing the ones complement.
629 /// <param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression" />.</param>
630 /// <param name="method">A <see cref="T:System.Reflection.MethodInfo" /> that represents the implementing method.</param>
631 /// <returns>An instance of <see cref="UnaryExpression"/>.</returns>
632 public static UnaryExpression OnesComplement(Expression expression, MethodInfo method) {
633 RequiresCanRead(expression, "expression");
634 if (method == null) {
635 if (TypeUtils.IsInteger(expression.Type)) {
636 return new UnaryExpression(ExpressionType.OnesComplement, expression, expression.Type, null);
638 return GetUserDefinedUnaryOperatorOrThrow(ExpressionType.OnesComplement, "op_OnesComplement", expression);
640 return GetMethodBasedUnaryOperator(ExpressionType.OnesComplement, expression, method);
643 ///<summary>Creates a <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that represents an explicit reference or boxing conversion where null is supplied if the conversion fails.</summary>
644 ///<returns>A <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that has the <see cref="P:Microsoft.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:Microsoft.Linq.Expressions.ExpressionType.TypeAs" /> and the <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Operand" /> and <see cref="P:Microsoft.Linq.Expressions.Expression.Type" /> properties set to the specified values.</returns>
645 ///<param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression" /> to set the <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Operand" /> property equal to.</param>
646 ///<param name="type">A <see cref="T:System.Type" /> to set the <see cref="P:Microsoft.Linq.Expressions.Expression.Type" /> property equal to.</param>
647 ///<exception cref="T:System.ArgumentNullException">
648 ///<paramref name="expression" /> or <paramref name="type" /> is null.</exception>
649 public static UnaryExpression TypeAs(Expression expression, Type type) {
650 RequiresCanRead(expression, "expression");
651 ContractUtils.RequiresNotNull(type, "type");
652 TypeUtils.ValidateType(type);
654 if (type.IsValueType && !TypeUtils.IsNullableType(type)) {
655 throw Error.IncorrectTypeForTypeAs(type);
657 return new UnaryExpression(ExpressionType.TypeAs, expression, type, null);
661 /// <summary>Creates a <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that represents an explicit unboxing.</summary>
663 /// <param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression" /> to unbox.</param>
664 /// <param name="type">The new <see cref="T:System.Type" /> of the expression.</param>
665 /// <returns>An instance of <see cref="UnaryExpression"/>.</returns>
666 public static UnaryExpression Unbox(Expression expression, Type type) {
667 RequiresCanRead(expression, "expression");
668 ContractUtils.RequiresNotNull(type, "type");
669 ContractUtils.Requires(
670 expression.Type.IsInterface || expression.Type == typeof(object),
671 "expression", Strings.InvalidUnboxType
673 ContractUtils.Requires(type.IsValueType, "type", Strings.InvalidUnboxType);
674 TypeUtils.ValidateType(type);
675 return new UnaryExpression(ExpressionType.Unbox, expression, type, null);
678 ///<summary>Creates a <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that represents a conversion operation.</summary>
679 ///<returns>A <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that has the <see cref="P:Microsoft.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:Microsoft.Linq.Expressions.ExpressionType.Convert" /> and the <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Operand" /> and <see cref="P:Microsoft.Linq.Expressions.Expression.Type" /> properties set to the specified values.</returns>
680 ///<param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression" /> to set the <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Operand" /> property equal to.</param>
681 ///<param name="type">A <see cref="T:System.Type" /> to set the <see cref="P:Microsoft.Linq.Expressions.Expression.Type" /> property equal to.</param>
682 ///<exception cref="T:System.ArgumentNullException">
683 ///<paramref name="expression" /> or <paramref name="type" /> is null.</exception>
684 ///<exception cref="T:System.InvalidOperationException">No conversion operator is defined between <paramref name="expression" />.Type and <paramref name="type" />.</exception>
685 public static UnaryExpression Convert(Expression expression, Type type) {
686 return Convert(expression, type, null);
689 ///<summary>Creates a <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that represents a conversion operation for which the implementing method is specified.</summary>
690 ///<returns>A <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that has the <see cref="P:Microsoft.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:Microsoft.Linq.Expressions.ExpressionType.Convert" /> and the <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Operand" />, <see cref="P:Microsoft.Linq.Expressions.Expression.Type" />, and <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Method" /> properties set to the specified values.</returns>
691 ///<param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression" /> to set the <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Operand" /> property equal to.</param>
692 ///<param name="type">A <see cref="T:System.Type" /> to set the <see cref="P:Microsoft.Linq.Expressions.Expression.Type" /> property equal to.</param>
693 ///<param name="method">A <see cref="T:System.Reflection.MethodInfo" /> to set the <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Method" /> property equal to.</param>
694 ///<exception cref="T:System.ArgumentNullException">
695 ///<paramref name="expression" /> or <paramref name="type" /> is null.</exception>
696 ///<exception cref="T:System.ArgumentException">
697 ///<paramref name="method" /> is not null and the method it represents returns void, is not static (Shared in Visual Basic), or does not take exactly one argument.</exception>
698 ///<exception cref="T:System.Reflection.AmbiguousMatchException">More than one method that matches the <paramref name="method" /> description was found.</exception>
699 ///<exception cref="T:System.InvalidOperationException">No conversion operator is defined between <paramref name="expression" />.Type and <paramref name="type" />.-or-<paramref name="expression" />.Type is not assignable to the argument type of the method represented by <paramref name="method" />.-or-The return type of the method represented by <paramref name="method" /> is not assignable to <paramref name="type" />.-or-<paramref name="expression" />.Type or <paramref name="type" /> is a nullable value type and the corresponding non-nullable value type does not equal the argument type or the return type, respectively, of the method represented by <paramref name="method" />.</exception>
700 public static UnaryExpression Convert(Expression expression, Type type, MethodInfo method) {
701 RequiresCanRead(expression, "expression");
702 ContractUtils.RequiresNotNull(type, "type");
703 TypeUtils.ValidateType(type);
705 if (method == null) {
706 if (TypeUtils.HasIdentityPrimitiveOrNullableConversion(expression.Type, type) ||
707 TypeUtils.HasReferenceConversion(expression.Type, type)) {
708 return new UnaryExpression(ExpressionType.Convert, expression, type, null);
710 return GetUserDefinedCoercionOrThrow(ExpressionType.Convert, expression, type);
712 return GetMethodBasedCoercionOperator(ExpressionType.Convert, expression, type, method);
715 ///<summary>Creates a <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that represents a conversion operation that throws an exception if the target type is overflowed.</summary>
716 ///<returns>A <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that has the <see cref="P:Microsoft.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:Microsoft.Linq.Expressions.ExpressionType.ConvertChecked" /> and the <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Operand" /> and <see cref="P:Microsoft.Linq.Expressions.Expression.Type" /> properties set to the specified values.</returns>
717 ///<param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression" /> to set the <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Operand" /> property equal to.</param>
718 ///<param name="type">A <see cref="T:System.Type" /> to set the <see cref="P:Microsoft.Linq.Expressions.Expression.Type" /> property equal to.</param>
719 ///<exception cref="T:System.ArgumentNullException">
720 ///<paramref name="expression" /> or <paramref name="type" /> is null.</exception>
721 ///<exception cref="T:System.InvalidOperationException">No conversion operator is defined between <paramref name="expression" />.Type and <paramref name="type" />.</exception>
722 public static UnaryExpression ConvertChecked(Expression expression, Type type) {
723 return ConvertChecked(expression, type, null);
726 ///<summary>Creates a <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that represents a conversion operation that throws an exception if the target type is overflowed and for which the implementing method is specified.</summary>
727 ///<returns>A <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that has the <see cref="P:Microsoft.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:Microsoft.Linq.Expressions.ExpressionType.ConvertChecked" /> and the <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Operand" />, <see cref="P:Microsoft.Linq.Expressions.Expression.Type" />, and <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Method" /> properties set to the specified values.</returns>
728 ///<param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression" /> to set the <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Operand" /> property equal to.</param>
729 ///<param name="type">A <see cref="T:System.Type" /> to set the <see cref="P:Microsoft.Linq.Expressions.Expression.Type" /> property equal to.</param>
730 ///<param name="method">A <see cref="T:System.Reflection.MethodInfo" /> to set the <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Method" /> property equal to.</param>
731 ///<exception cref="T:System.ArgumentNullException">
732 ///<paramref name="expression" /> or <paramref name="type" /> is null.</exception>
733 ///<exception cref="T:System.ArgumentException">
734 ///<paramref name="method" /> is not null and the method it represents returns void, is not static (Shared in Visual Basic), or does not take exactly one argument.</exception>
735 ///<exception cref="T:System.Reflection.AmbiguousMatchException">More than one method that matches the <paramref name="method" /> description was found.</exception>
736 ///<exception cref="T:System.InvalidOperationException">No conversion operator is defined between <paramref name="expression" />.Type and <paramref name="type" />.-or-<paramref name="expression" />.Type is not assignable to the argument type of the method represented by <paramref name="method" />.-or-The return type of the method represented by <paramref name="method" /> is not assignable to <paramref name="type" />.-or-<paramref name="expression" />.Type or <paramref name="type" /> is a nullable value type and the corresponding non-nullable value type does not equal the argument type or the return type, respectively, of the method represented by <paramref name="method" />.</exception>
737 public static UnaryExpression ConvertChecked(Expression expression, Type type, MethodInfo method) {
738 RequiresCanRead(expression, "expression");
739 ContractUtils.RequiresNotNull(type, "type");
740 TypeUtils.ValidateType(type);
742 if (method == null) {
743 if (TypeUtils.HasIdentityPrimitiveOrNullableConversion(expression.Type, type)) {
744 return new UnaryExpression(ExpressionType.ConvertChecked, expression, type, null);
746 if (TypeUtils.HasReferenceConversion(expression.Type, type)) {
747 return new UnaryExpression(ExpressionType.Convert, expression, type, null);
749 return GetUserDefinedCoercionOrThrow(ExpressionType.ConvertChecked, expression, type);
751 return GetMethodBasedCoercionOperator(ExpressionType.ConvertChecked, expression, type, method);
754 ///<summary>Creates a <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that represents getting the length of a one-dimensional array.</summary>
755 ///<returns>A <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that has the <see cref="P:Microsoft.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:Microsoft.Linq.Expressions.ExpressionType.ArrayLength" /> and the <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Operand" /> property equal to <paramref name="array" />.</returns>
756 ///<param name="array">An <see cref="T:Microsoft.Linq.Expressions.Expression" /> to set the <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Operand" /> property equal to.</param>
757 ///<exception cref="T:System.ArgumentNullException">
758 ///<paramref name="array" /> is null.</exception>
759 ///<exception cref="T:System.ArgumentException">
760 ///<paramref name="array" />.Type does not represent an array type.</exception>
761 public static UnaryExpression ArrayLength(Expression array) {
762 ContractUtils.RequiresNotNull(array, "array");
763 if (!array.Type.IsArray || !typeof(Array).IsAssignableFrom(array.Type)) {
764 throw Error.ArgumentMustBeArray();
766 if (array.Type.GetArrayRank() != 1) {
767 throw Error.ArgumentMustBeSingleDimensionalArrayType();
769 return new UnaryExpression(ExpressionType.ArrayLength, array, typeof(int), null);
772 ///<summary>Creates a <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that represents an expression that has a constant value of type <see cref="T:Microsoft.Linq.Expressions.Expression" />.</summary>
773 ///<returns>A <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that has the <see cref="P:Microsoft.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:Microsoft.Linq.Expressions.ExpressionType.Quote" /> and the <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Operand" /> property set to the specified value.</returns>
774 ///<param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression" /> to set the <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Operand" /> property equal to.</param>
775 ///<exception cref="T:System.ArgumentNullException">
776 ///<paramref name="expression" /> is null.</exception>
777 public static UnaryExpression Quote(Expression expression) {
778 RequiresCanRead(expression, "expression");
779 ContractUtils.Requires(expression is LambdaExpression, Strings.QuotedExpressionMustBeLambda);
780 return new UnaryExpression(ExpressionType.Quote, expression, expression.GetType(), null);
784 /// Creates a <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that represents a rethrowing of an exception.
786 /// <returns>A <see cref="T:Microsoft.Linq.Expressions.UnaryExpression"/> that represents a rethrowing of an exception.</returns>
787 public static UnaryExpression Rethrow() {
792 /// Creates a <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that represents a rethrowing of an exception with a given type.
794 ///<param name="type">The new <see cref="T:System.Type" /> of the expression.</param>
795 /// <returns>A <see cref="T:Microsoft.Linq.Expressions.UnaryExpression"/> that represents a rethrowing of an exception.</returns>
796 public static UnaryExpression Rethrow(Type type) {
797 return Throw(null, type);
801 /// Creates a <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that represents a throwing of an exception.
803 /// <param name="value">An <see cref="T:Microsoft.Linq.Expressions.Expression" />.</param>
804 /// <returns>A <see cref="T:Microsoft.Linq.Expressions.UnaryExpression"/> that represents the exception.</returns>
805 public static UnaryExpression Throw(Expression value) {
806 return Throw(value, typeof(void));
810 /// Creates a <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that represents a throwing of a value with a given type.
812 /// <param name="value">An <see cref="T:Microsoft.Linq.Expressions.Expression" />.</param>
813 /// <param name="type">The new <see cref="T:System.Type" /> of the expression.</param>
814 /// <returns>A <see cref="T:Microsoft.Linq.Expressions.UnaryExpression"/> that represents the exception.</returns>
815 public static UnaryExpression Throw(Expression value, Type type) {
816 ContractUtils.RequiresNotNull(type, "type");
817 TypeUtils.ValidateType(type);
820 RequiresCanRead(value, "value");
821 ContractUtils.Requires(!value.Type.IsValueType, "value", Strings.ArgumentMustNotHaveValueType);
823 return new UnaryExpression(ExpressionType.Throw, value, type, null);
827 /// Creates a <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that represents the incrementing of the expression by 1.
829 /// <param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression"></see> to increment.</param>
830 /// <returns>A <see cref="T:Microsoft.Linq.Expressions.UnaryExpression"/> that represents the incremented expression.</returns>
831 public static UnaryExpression Increment(Expression expression) {
832 return Increment(expression, null);
836 /// Creates a <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that represents the incrementing of the expression by 1.
838 /// <param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression"></see> to increment.</param>
839 ///<param name="method">A <see cref="T:System.Reflection.MethodInfo" /> that represents the implementing method.</param>
840 /// <returns>A <see cref="T:Microsoft.Linq.Expressions.UnaryExpression"/> that represents the incremented expression.</returns>
841 public static UnaryExpression Increment(Expression expression, MethodInfo method) {
842 RequiresCanRead(expression, "expression");
843 if (method == null) {
844 if (TypeUtils.IsArithmetic(expression.Type)) {
845 return new UnaryExpression(ExpressionType.Increment, expression, expression.Type, null);
847 return GetUserDefinedUnaryOperatorOrThrow(ExpressionType.Increment, "op_Increment", expression);
849 return GetMethodBasedUnaryOperator(ExpressionType.Increment, expression, method);
853 /// Creates a <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that represents the decrementing of the expression by 1.
855 /// <param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression"></see> to decrement.</param>
856 /// <returns>A <see cref="T:Microsoft.Linq.Expressions.UnaryExpression"/> that represents the decremented expression.</returns>
857 public static UnaryExpression Decrement(Expression expression) {
858 return Decrement(expression, null);
862 /// Creates a <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that represents the decrementing of the expression by 1.
864 /// <param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression"></see> to decrement.</param>
865 ///<param name="method">A <see cref="T:System.Reflection.MethodInfo" /> that represents the implementing method.</param>
866 /// <returns>A <see cref="T:Microsoft.Linq.Expressions.UnaryExpression"/> that represents the decremented expression.</returns>
867 public static UnaryExpression Decrement(Expression expression, MethodInfo method) {
868 RequiresCanRead(expression, "expression");
869 if (method == null) {
870 if (TypeUtils.IsArithmetic(expression.Type)) {
871 return new UnaryExpression(ExpressionType.Decrement, expression, expression.Type, null);
873 return GetUserDefinedUnaryOperatorOrThrow(ExpressionType.Decrement, "op_Decrement", expression);
875 return GetMethodBasedUnaryOperator(ExpressionType.Decrement, expression, method);
879 /// Creates a <see cref="UnaryExpression"/> that increments the expression by 1
880 /// and assigns the result back to the expression.
882 /// <param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression"></see> to apply the operations on.</param>
883 /// <returns>A <see cref="T:Microsoft.Linq.Expressions.UnaryExpression"/> that represents the resultant expression.</returns>
884 public static UnaryExpression PreIncrementAssign(Expression expression) {
885 return MakeOpAssignUnary(ExpressionType.PreIncrementAssign, expression, null);
890 /// Creates a <see cref="UnaryExpression"/> that increments the expression by 1
891 /// and assigns the result back to the expression.
893 /// <param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression"></see> to apply the operations on.</param>
894 /// <param name="method">A <see cref="T:System.Reflection.MethodInfo" /> that represents the implementing method.</param>
895 /// <returns>A <see cref="T:Microsoft.Linq.Expressions.UnaryExpression"/> that represents the resultant expression.</returns>
896 public static UnaryExpression PreIncrementAssign(Expression expression, MethodInfo method) {
897 return MakeOpAssignUnary(ExpressionType.PreIncrementAssign, expression, method);
901 /// Creates a <see cref="UnaryExpression"/> that decrements the expression by 1
902 /// and assigns the result back to the expression.
904 /// <param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression"></see> to apply the operations on.</param>
905 /// <returns>A <see cref="T:Microsoft.Linq.Expressions.UnaryExpression"/> that represents the resultant expression.</returns>
906 public static UnaryExpression PreDecrementAssign(Expression expression) {
907 return MakeOpAssignUnary(ExpressionType.PreDecrementAssign, expression, null);
911 /// Creates a <see cref="UnaryExpression"/> that decrements the expression by 1
912 /// and assigns the result back to the expression.
914 /// <param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression"></see> to apply the operations on.</param>
915 /// <param name="method">A <see cref="T:System.Reflection.MethodInfo" /> that represents the implementing method.</param>
916 /// <returns>A <see cref="T:Microsoft.Linq.Expressions.UnaryExpression"/> that represents the resultant expression.</returns>
917 public static UnaryExpression PreDecrementAssign(Expression expression, MethodInfo method) {
918 return MakeOpAssignUnary(ExpressionType.PreDecrementAssign, expression, method);
922 /// Creates a <see cref="UnaryExpression"/> that represents the assignment of the expression
923 /// followed by a subsequent increment by 1 of the original expression.
925 /// <param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression"></see> to apply the operations on.</param>
926 /// <returns>A <see cref="T:Microsoft.Linq.Expressions.UnaryExpression"/> that represents the resultant expression.</returns>
927 public static UnaryExpression PostIncrementAssign(Expression expression) {
928 return MakeOpAssignUnary(ExpressionType.PostIncrementAssign, expression, null);
932 /// Creates a <see cref="UnaryExpression"/> that represents the assignment of the expression
933 /// followed by a subsequent increment by 1 of the original expression.
935 /// <param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression"></see> to apply the operations on.</param>
936 /// <param name="method">A <see cref="T:System.Reflection.MethodInfo" /> that represents the implementing method.</param>
937 /// <returns>A <see cref="T:Microsoft.Linq.Expressions.UnaryExpression"/> that represents the resultant expression.</returns>
938 public static UnaryExpression PostIncrementAssign(Expression expression, MethodInfo method) {
939 return MakeOpAssignUnary(ExpressionType.PostIncrementAssign, expression, method);
943 /// Creates a <see cref="UnaryExpression"/> that represents the assignment of the expression
944 /// followed by a subsequent decrement by 1 of the original expression.
946 /// <param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression"></see> to apply the operations on.</param>
947 /// <returns>A <see cref="T:Microsoft.Linq.Expressions.UnaryExpression"/> that represents the resultant expression.</returns>
948 public static UnaryExpression PostDecrementAssign(Expression expression) {
949 return MakeOpAssignUnary(ExpressionType.PostDecrementAssign, expression, null);
953 /// Creates a <see cref="UnaryExpression"/> that represents the assignment of the expression
954 /// followed by a subsequent decrement by 1 of the original expression.
956 /// <param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression"></see> to apply the operations on.</param>
957 /// <param name="method">A <see cref="T:System.Reflection.MethodInfo" /> that represents the implementing method.</param>
958 /// <returns>A <see cref="T:Microsoft.Linq.Expressions.UnaryExpression"/> that represents the resultant expression.</returns>
959 public static UnaryExpression PostDecrementAssign(Expression expression, MethodInfo method) {
960 return MakeOpAssignUnary(ExpressionType.PostDecrementAssign, expression, method);
963 private static UnaryExpression MakeOpAssignUnary(ExpressionType kind, Expression expression, MethodInfo method) {
964 RequiresCanRead(expression, "expression");
965 RequiresCanWrite(expression, "expression");
967 UnaryExpression result;
968 if (method == null) {
969 if (TypeUtils.IsArithmetic(expression.Type)) {
970 return new UnaryExpression(kind, expression, expression.Type, null);
973 if (kind == ExpressionType.PreIncrementAssign || kind == ExpressionType.PostIncrementAssign) {
974 name = "op_Increment";
976 name = "op_Decrement";
978 result = GetUserDefinedUnaryOperatorOrThrow(kind, name, expression);
980 result = GetMethodBasedUnaryOperator(kind, expression, method);
982 // return type must be assignable back to the operand type
983 if (!TypeUtils.AreReferenceAssignable(expression.Type, result.Type)) {
984 throw Error.UserDefinedOpMustHaveValidReturnType(kind, method.Name);