1 /* ****************************************************************************
3 * Copyright (c) Microsoft Corporation.
5 * This source code is subject to terms and conditions of the Apache License, Version 2.0. 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 Apache License, Version 2.0, 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 Apache License, Version 2.0.
11 * You must not remove this notice, or any other, from this software.
14 * ***************************************************************************/
17 using System.Diagnostics;
18 using System.Dynamic.Utils;
19 using System.Reflection;
20 using System.Runtime.CompilerServices;
27 namespace Microsoft.Scripting.Ast {
29 namespace System.Linq.Expressions {
33 /// Represents an expression that has a unary operator.
36 [DebuggerTypeProxy(typeof(Expression.UnaryExpressionProxy))]
38 public sealed class UnaryExpression : Expression {
39 private readonly Expression _operand;
40 private readonly MethodInfo _method;
41 private readonly ExpressionType _nodeType;
42 private readonly Type _type;
44 internal UnaryExpression(ExpressionType nodeType, Expression expression, Type type, MethodInfo method) {
45 _operand = expression;
52 /// Gets the static type of the expression that this <see cref="Expression" /> represents. (Inherited from <see cref="Expression"/>.)
54 /// <returns>The <see cref="Type"/> that represents the static type of the expression.</returns>
55 public sealed override Type Type {
60 /// Returns the node type of this <see cref="Expression" />. (Inherited from <see cref="Expression" />.)
62 /// <returns>The <see cref="ExpressionType"/> that represents this expression.</returns>
63 public sealed override ExpressionType NodeType {
64 get { return _nodeType; }
68 /// Gets the operand of the unary operation.
70 /// <returns> An <see cref="ExpressionType"/> that represents the operand of the unary operation.</returns>
71 public Expression Operand {
72 get { return _operand; }
76 /// Gets the implementing method for the unary operation.
78 /// <returns>The <see cref="MethodInfo"/> that represents the implementing method.</returns>
79 public MethodInfo Method {
80 get { return _method; }
84 /// Gets a value that indicates whether the expression tree node represents a lifted call to an operator.
86 /// <returns>true if the node represents a lifted call; otherwise, false.</returns>
87 public bool IsLifted {
89 if (NodeType == ExpressionType.TypeAs || NodeType == ExpressionType.Quote || NodeType == ExpressionType.Throw) {
92 bool operandIsNullable = TypeUtils.IsNullableType(_operand.Type);
93 bool resultIsNullable = TypeUtils.IsNullableType(this.Type);
94 if (_method != null) {
95 return (operandIsNullable && !TypeUtils.AreEquivalent(_method.GetParametersCached()[0].ParameterType, _operand.Type)) ||
96 (resultIsNullable && !TypeUtils.AreEquivalent(_method.ReturnType, this.Type));
98 return operandIsNullable || resultIsNullable;
103 /// 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.
105 /// <returns>true if the operator's return type is lifted to a nullable type; otherwise, false.</returns>
106 public bool IsLiftedToNull {
108 return IsLifted && TypeUtils.IsNullableType(this.Type);
113 /// Dispatches to the specific visit method for this node type.
115 protected internal override Expression Accept(ExpressionVisitor visitor) {
116 return visitor.VisitUnary(this);
120 /// Gets a value that indicates whether the expression tree node can be reduced.
122 public override bool CanReduce {
125 case ExpressionType.PreIncrementAssign:
126 case ExpressionType.PreDecrementAssign:
127 case ExpressionType.PostIncrementAssign:
128 case ExpressionType.PostDecrementAssign:
136 /// Reduces the expression node to a simpler expression.
137 /// If CanReduce returns true, this should return a valid expression.
138 /// This method is allowed to return another node which itself
141 /// <returns>The reduced expression.</returns>
142 public override Expression Reduce() {
144 switch (_operand.NodeType) {
145 case ExpressionType.Index:
146 return ReduceIndex();
147 case ExpressionType.MemberAccess:
148 return ReduceMember();
150 return ReduceVariable();
156 private bool IsPrefix {
157 get { return _nodeType == ExpressionType.PreIncrementAssign || _nodeType == ExpressionType.PreDecrementAssign; }
160 private UnaryExpression FunctionalOp(Expression operand) {
161 ExpressionType functional;
162 if (_nodeType == ExpressionType.PreIncrementAssign || _nodeType == ExpressionType.PostIncrementAssign) {
163 functional = ExpressionType.Increment;
165 functional = ExpressionType.Decrement;
167 return new UnaryExpression(functional, operand, operand.Type, _method);
170 private Expression ReduceVariable() {
173 // ... is reduced into ...
175 return Assign(_operand, FunctionalOp(_operand));
178 // ... is reduced into ...
182 var temp = Parameter(_operand.Type, null);
185 Assign(temp, _operand),
186 Assign(_operand, FunctionalOp(temp)),
191 private Expression ReduceMember() {
192 var member = (MemberExpression)_operand;
193 if (member.Expression == null) {
194 //static member, reduce the same as variable
195 return ReduceVariable();
197 var temp1 = Parameter(member.Expression.Type, null);
198 var initTemp1 = Assign(temp1, member.Expression);
199 member = MakeMemberAccess(temp1, member.Member);
203 // ... is reduced into ...
205 // temp1.member = op(temp1.member)
209 Assign(member, FunctionalOp(member))
214 // ... is reduced into ...
216 // temp2 = temp1.member
217 // temp1.member = op(temp2)
219 var temp2 = Parameter(member.Type, null);
221 new[] { temp1, temp2 },
223 Assign(temp2, member),
224 Assign(member, FunctionalOp(temp2)),
230 private Expression ReduceIndex() {
231 // left[a0, a1, ... aN] (op)
233 // ... is reduced into ...
239 // tempValue = tempObj[tempArg0, ... tempArgN]
240 // tempObj[tempArg0, ... tempArgN] = op(tempValue)
243 bool prefix = IsPrefix;
244 var index = (IndexExpression)_operand;
245 int count = index.Arguments.Count;
246 var block = new Expression[count + (prefix ? 2 : 4)];
247 var temps = new ParameterExpression[count + (prefix ? 1 : 2)];
248 var args = new ParameterExpression[count];
251 temps[i] = Parameter(index.Object.Type, null);
252 block[i] = Assign(temps[i], index.Object);
255 var arg = index.Arguments[i - 1];
256 args[i - 1] = temps[i] = Parameter(arg.Type, null);
257 block[i] = Assign(temps[i], arg);
260 index = MakeIndex(temps[0], index.Indexer, new TrueReadOnlyCollection<Expression>(args));
262 var lastTemp = temps[i] = Parameter(index.Type, null);
263 block[i] = Assign(temps[i], index);
265 Debug.Assert(i == temps.Length);
266 block[i++] = Assign(index, FunctionalOp(lastTemp));
267 block[i++] = lastTemp;
269 Debug.Assert(i == temps.Length);
270 block[i++] = Assign(index, FunctionalOp(index));
272 Debug.Assert(i == block.Length);
273 return Block(new TrueReadOnlyCollection<ParameterExpression>(temps), new TrueReadOnlyCollection<Expression>(block));
277 /// Creates a new expression that is like this one, but using the
278 /// supplied children. If all of the children are the same, it will
279 /// return this expression.
281 /// <param name="operand">The <see cref="Operand" /> property of the result.</param>
282 /// <returns>This expression if no children changed, or an expression with the updated children.</returns>
283 public UnaryExpression Update(Expression operand) {
284 if (operand == Operand) {
287 return Expression.MakeUnary(NodeType, operand, Type, Method);
291 public partial class Expression {
294 /// Creates a <see cref="UnaryExpression"></see>, given an operand, by calling the appropriate factory method.
296 /// <param name="unaryType">The <see cref="ExpressionType"></see> that specifies the type of unary operation.</param>
297 /// <param name="operand">An <see cref="Expression"></see> that represents the operand.</param>
298 /// <param name="type">The <see cref="Type"></see> that specifies the type to be converted to (pass null if not applicable).</param>
299 /// <returns>The <see cref="UnaryExpression"></see> that results from calling the appropriate factory method.</returns>
300 /// <exception cref="ArgumentException">Thrown when <paramref name="unaryType"/> does not correspond to a unary expression.</exception>
301 /// <exception cref="ArgumentNullException">Thrown when <paramref name="operand"/> is null.</exception>
302 public static UnaryExpression MakeUnary(ExpressionType unaryType, Expression operand, Type type) {
303 return MakeUnary(unaryType, operand, type, null);
307 /// Creates a <see cref="UnaryExpression"></see>, given an operand and implementing method, by calling the appropriate factory method.
309 /// <param name="unaryType">The <see cref="ExpressionType"></see> that specifies the type of unary operation.</param>
310 /// <param name="operand">An <see cref="Expression"></see> that represents the operand.</param>
311 /// <param name="type">The <see cref="Type"></see> that specifies the type to be converted to (pass null if not applicable).</param>
312 /// <param name="method">The <see cref="MethodInfo"></see> that represents the implementing method.</param>
313 /// <returns>The <see cref="UnaryExpression"></see> that results from calling the appropriate factory method.</returns>
314 /// <exception cref="ArgumentException">Thrown when <paramref name="unaryType"/> does not correspond to a unary expression.</exception>
315 /// <exception cref="ArgumentNullException">Thrown when <paramref name="operand"/> is null.</exception>
316 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
317 public static UnaryExpression MakeUnary(ExpressionType unaryType, Expression operand, Type type, MethodInfo method) {
319 case ExpressionType.Negate:
320 return Negate(operand, method);
321 case ExpressionType.NegateChecked:
322 return NegateChecked(operand, method);
323 case ExpressionType.Not:
324 return Not(operand, method);
325 case ExpressionType.IsFalse:
326 return IsFalse(operand, method);
327 case ExpressionType.IsTrue:
328 return IsTrue(operand, method);
329 case ExpressionType.OnesComplement:
330 return OnesComplement(operand, method);
331 case ExpressionType.ArrayLength:
332 return ArrayLength(operand);
333 case ExpressionType.Convert:
334 return Convert(operand, type, method);
335 case ExpressionType.ConvertChecked:
336 return ConvertChecked(operand, type, method);
337 case ExpressionType.Throw:
338 return Throw(operand, type);
339 case ExpressionType.TypeAs:
340 return TypeAs(operand, type);
341 case ExpressionType.Quote:
342 return Quote(operand);
343 case ExpressionType.UnaryPlus:
344 return UnaryPlus(operand, method);
345 case ExpressionType.Unbox:
346 return Unbox(operand, type);
347 case ExpressionType.Increment:
348 return Increment(operand, method);
349 case ExpressionType.Decrement:
350 return Decrement(operand, method);
351 case ExpressionType.PreIncrementAssign:
352 return PreIncrementAssign(operand, method);
353 case ExpressionType.PostIncrementAssign:
354 return PostIncrementAssign(operand, method);
355 case ExpressionType.PreDecrementAssign:
356 return PreDecrementAssign(operand, method);
357 case ExpressionType.PostDecrementAssign:
358 return PostDecrementAssign(operand, method);
360 throw Error.UnhandledUnary(unaryType);
364 private static UnaryExpression GetUserDefinedUnaryOperatorOrThrow(ExpressionType unaryType, string name, Expression operand) {
365 UnaryExpression u = GetUserDefinedUnaryOperator(unaryType, name, operand);
367 ValidateParamswithOperandsOrThrow(u.Method.GetParametersCached()[0].ParameterType, operand.Type, unaryType, name);
370 throw Error.UnaryOperatorNotDefined(unaryType, operand.Type);
373 private static UnaryExpression GetUserDefinedUnaryOperator(ExpressionType unaryType, string name, Expression operand) {
374 Type operandType = operand.Type;
375 Type[] types = new Type[] { operandType };
376 Type nnOperandType = TypeUtils.GetNonNullableType(operandType);
377 BindingFlags flags = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
378 MethodInfo method = nnOperandType.GetMethodValidated(name, flags, null, types, null);
379 if (method != null) {
380 return new UnaryExpression(unaryType, operand, method.ReturnType, method);
383 if (TypeUtils.IsNullableType(operandType)) {
384 types[0] = nnOperandType;
385 method = nnOperandType.GetMethodValidated(name, flags, null, types, null);
386 if (method != null && method.ReturnType.IsValueType && !TypeUtils.IsNullableType(method.ReturnType)) {
387 return new UnaryExpression(unaryType, operand, TypeUtils.GetNullableType(method.ReturnType), method);
393 private static UnaryExpression GetMethodBasedUnaryOperator(ExpressionType unaryType, Expression operand, MethodInfo method) {
394 System.Diagnostics.Debug.Assert(method != null);
395 ValidateOperator(method);
396 ParameterInfo[] pms = method.GetParametersCached();
398 throw Error.IncorrectNumberOfMethodCallArguments(method);
399 if (ParameterIsAssignable(pms[0], operand.Type)) {
400 ValidateParamswithOperandsOrThrow(pms[0].ParameterType, operand.Type, unaryType, method.Name);
401 return new UnaryExpression(unaryType, operand, method.ReturnType, method);
403 // check for lifted call
404 if (TypeUtils.IsNullableType(operand.Type) &&
405 ParameterIsAssignable(pms[0], TypeUtils.GetNonNullableType(operand.Type)) &&
406 method.ReturnType.IsValueType && !TypeUtils.IsNullableType(method.ReturnType)) {
407 return new UnaryExpression(unaryType, operand, TypeUtils.GetNullableType(method.ReturnType), method);
410 throw Error.OperandTypesDoNotMatchParameters(unaryType, method.Name);
413 private static UnaryExpression GetUserDefinedCoercionOrThrow(ExpressionType coercionType, Expression expression, Type convertToType) {
414 UnaryExpression u = GetUserDefinedCoercion(coercionType, expression, convertToType);
418 throw Error.CoercionOperatorNotDefined(expression.Type, convertToType);
421 private static UnaryExpression GetUserDefinedCoercion(ExpressionType coercionType, Expression expression, Type convertToType) {
422 MethodInfo method = TypeUtils.GetUserDefinedCoercionMethod(expression.Type, convertToType, false);
423 if (method != null) {
424 return new UnaryExpression(coercionType, expression, convertToType, method);
430 private static UnaryExpression GetMethodBasedCoercionOperator(ExpressionType unaryType, Expression operand, Type convertToType, MethodInfo method) {
431 System.Diagnostics.Debug.Assert(method != null);
432 ValidateOperator(method);
433 ParameterInfo[] pms = method.GetParametersCached();
434 if (pms.Length != 1) {
435 throw Error.IncorrectNumberOfMethodCallArguments(method);
437 if (ParameterIsAssignable(pms[0], operand.Type) && TypeUtils.AreEquivalent(method.ReturnType, convertToType)) {
438 return new UnaryExpression(unaryType, operand, method.ReturnType, method);
440 // check for lifted call
441 if ((TypeUtils.IsNullableType(operand.Type) || TypeUtils.IsNullableType(convertToType)) &&
442 ParameterIsAssignable(pms[0], TypeUtils.GetNonNullableType(operand.Type)) &&
443 TypeUtils.AreEquivalent(method.ReturnType, TypeUtils.GetNonNullableType(convertToType))) {
444 return new UnaryExpression(unaryType, operand, convertToType, method);
446 throw Error.OperandTypesDoNotMatchParameters(unaryType, method.Name);
450 /// Creates a <see cref="UnaryExpression"></see> that represents an arithmetic negation operation.
452 /// <param name="expression">An <see cref="Expression"></see> to set the <see cref="P:UnaryExpression.Operand"></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> properties set to the specified value.</returns>
454 /// <exception cref="ArgumentNullException">Thrown when <paramref name="expression"/> is null.</exception>
455 /// <exception cref="InvalidOperationException">Thrown when the unary minus operator is not defined for <see cref="P:Expression.Type"></see></exception>
456 public static UnaryExpression Negate(Expression expression) {
457 return Negate(expression, null);
461 /// Creates a <see cref="UnaryExpression"></see> that represents an arithmetic negation operation.
463 /// <param name="expression">An <see cref="Expression"></see> to set the <see cref="P:UnaryExpression.Operand"></see> property equal to.</param>
464 /// <param name="method">A <see cref="MethodInfo"></see> to set the <see cref="P:UnaryExpression.Method"></see> property equal to.</param>
465 /// <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>
466 /// <exception cref="ArgumentNullException">Thrown when <paramref name="expression"/> is null.</exception>
467 /// <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>
468 /// <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>
469 public static UnaryExpression Negate(Expression expression, MethodInfo method) {
470 RequiresCanRead(expression, "expression");
471 if (method == null) {
472 if (TypeUtils.IsArithmetic(expression.Type) && !TypeUtils.IsUnsignedInt(expression.Type)) {
473 return new UnaryExpression(ExpressionType.Negate, expression, expression.Type, null);
475 return GetUserDefinedUnaryOperatorOrThrow(ExpressionType.Negate, "op_UnaryNegation", expression);
477 return GetMethodBasedUnaryOperator(ExpressionType.Negate, expression, method);
481 /// Creates a <see cref="UnaryExpression"></see> that represents a unary plus operation.
483 /// <param name="expression">An <see cref="Expression"></see> to set the <see cref="UnaryExpression.Operand"></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> property set to the specified value.</returns>
485 /// <exception cref="ArgumentNullException">Thrown when <paramref name="expression"/> is null.</exception>
486 /// <exception cref="InvalidOperationException">Thown when the unary minus operator is not defined for expression.Type.</exception>
487 public static UnaryExpression UnaryPlus(Expression expression) {
488 return UnaryPlus(expression, null);
492 /// Creates a <see cref="UnaryExpression"></see> that represents a unary plus operation.
494 /// <param name="expression">An <see cref="Expression"></see> to set the <see cref="UnaryExpression.Operand"></see> property equal to.</param>
495 /// <param name="method">A <see cref="MethodInfo"></see> to set the <see cref="UnaryExpression.Method"></see> property equal to.</param>
496 /// <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>
497 /// <exception cref="ArgumentNullException">Thrown when <paramref name="expression"/> is null.</exception>
498 /// <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>
499 /// <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>
500 public static UnaryExpression UnaryPlus(Expression expression, MethodInfo method) {
501 RequiresCanRead(expression, "expression");
502 if (method == null) {
503 if (TypeUtils.IsArithmetic(expression.Type)) {
504 return new UnaryExpression(ExpressionType.UnaryPlus, expression, expression.Type, null);
506 return GetUserDefinedUnaryOperatorOrThrow(ExpressionType.UnaryPlus, "op_UnaryPlus", expression);
508 return GetMethodBasedUnaryOperator(ExpressionType.UnaryPlus, expression, method);
511 /// <summary>Creates a <see cref="T:System.Linq.Expressions.UnaryExpression" /> that represents an arithmetic negation operation that has overflow checking.</summary>
512 /// <returns>A <see cref="T:System.Linq.Expressions.UnaryExpression" /> that has the <see cref="P:System.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:System.Linq.Expressions.ExpressionType.NegateChecked" /> and the <see cref="P:System.Linq.Expressions.UnaryExpression.Operand" /> property set to the specified value.</returns>
513 /// <param name="expression">An <see cref="T:System.Linq.Expressions.Expression" /> to set the <see cref="P:System.Linq.Expressions.UnaryExpression.Operand" /> property equal to.</param>
514 /// <exception cref="T:System.ArgumentNullException">
515 /// Thrown when <paramref name="expression" /> is null.</exception>
516 /// <exception cref="T:System.InvalidOperationException">Thrown when the unary minus operator is not defined for <paramref name="expression" />.Type.</exception>
517 public static UnaryExpression NegateChecked(Expression expression) {
518 return NegateChecked(expression, null);
521 ///<summary>Creates a <see cref="T:System.Linq.Expressions.UnaryExpression" /> that represents an arithmetic negation operation that has overflow checking. The implementing method can be specified.</summary>
522 ///<returns>A <see cref="T:System.Linq.Expressions.UnaryExpression" /> that has the <see cref="P:System.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:System.Linq.Expressions.ExpressionType.NegateChecked" /> and the <see cref="P:System.Linq.Expressions.UnaryExpression.Operand" /> and <see cref="P:System.Linq.Expressions.UnaryExpression.Method" /> properties set to the specified values.</returns>
523 ///<param name="expression">An <see cref="T:System.Linq.Expressions.Expression" /> to set the <see cref="P:System.Linq.Expressions.UnaryExpression.Operand" /> property equal to.</param>
524 ///<param name="method">A <see cref="T:System.Reflection.MethodInfo" /> to set the <see cref="P:System.Linq.Expressions.UnaryExpression.Method" /> property equal to.</param>
525 ///<exception cref="T:System.ArgumentNullException">
526 ///<paramref name="expression" /> is null.</exception>
527 ///<exception cref="T:System.ArgumentException">
528 ///<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>
529 ///<exception cref="T:System.InvalidOperationException">
530 ///<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>
531 public static UnaryExpression NegateChecked(Expression expression, MethodInfo method) {
532 RequiresCanRead(expression, "expression");
533 if (method == null) {
534 if (TypeUtils.IsArithmetic(expression.Type) && !TypeUtils.IsUnsignedInt(expression.Type)) {
535 return new UnaryExpression(ExpressionType.NegateChecked, expression, expression.Type, null);
537 return GetUserDefinedUnaryOperatorOrThrow(ExpressionType.NegateChecked, "op_UnaryNegation", expression);
539 return GetMethodBasedUnaryOperator(ExpressionType.NegateChecked, expression, method);
542 ///<summary>Creates a <see cref="T:System.Linq.Expressions.UnaryExpression" /> that represents a bitwise complement operation.</summary>
543 ///<returns>A <see cref="T:System.Linq.Expressions.UnaryExpression" /> that has the <see cref="P:System.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:System.Linq.Expressions.ExpressionType.Not" /> and the <see cref="P:System.Linq.Expressions.UnaryExpression.Operand" /> property set to the specified value.</returns>
544 ///<param name="expression">An <see cref="T:System.Linq.Expressions.Expression" /> to set the <see cref="P:System.Linq.Expressions.UnaryExpression.Operand" /> property equal to.</param>
545 ///<exception cref="T:System.ArgumentNullException">
546 ///<paramref name="expression" /> is null.</exception>
547 ///<exception cref="T:System.InvalidOperationException">The unary not operator is not defined for <paramref name="expression" />.Type.</exception>
548 public static UnaryExpression Not(Expression expression) {
549 return Not(expression, null);
552 ///<summary>Creates a <see cref="T:System.Linq.Expressions.UnaryExpression" /> that represents a bitwise complement operation. The implementing method can be specified.</summary>
553 ///<returns>A <see cref="T:System.Linq.Expressions.UnaryExpression" /> that has the <see cref="P:System.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:System.Linq.Expressions.ExpressionType.Not" /> and the <see cref="P:System.Linq.Expressions.UnaryExpression.Operand" /> and <see cref="P:System.Linq.Expressions.UnaryExpression.Method" /> properties set to the specified values.</returns>
554 ///<param name="expression">An <see cref="T:System.Linq.Expressions.Expression" /> to set the <see cref="P:System.Linq.Expressions.UnaryExpression.Operand" /> property equal to.</param>
555 ///<param name="method">A <see cref="T:System.Reflection.MethodInfo" /> to set the <see cref="P:System.Linq.Expressions.UnaryExpression.Method" /> property equal to.</param>
556 ///<exception cref="T:System.ArgumentNullException">
557 ///<paramref name="expression" /> is null.</exception>
558 ///<exception cref="T:System.ArgumentException">
559 ///<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>
560 ///<exception cref="T:System.InvalidOperationException">
561 ///<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>
562 public static UnaryExpression Not(Expression expression, MethodInfo method) {
563 RequiresCanRead(expression, "expression");
564 if (method == null) {
565 if (TypeUtils.IsIntegerOrBool(expression.Type)) {
566 return new UnaryExpression(ExpressionType.Not, expression, expression.Type, null);
568 UnaryExpression u = GetUserDefinedUnaryOperator(ExpressionType.Not, "op_LogicalNot", expression);
572 return GetUserDefinedUnaryOperatorOrThrow(ExpressionType.Not, "op_OnesComplement", expression);
574 return GetMethodBasedUnaryOperator(ExpressionType.Not, expression, method);
578 /// Returns whether the expression evaluates to false.
580 /// <param name="expression">An <see cref="T:System.Linq.Expressions.Expression" /> to evaluate.</param>
581 /// <returns>An instance of <see cref="UnaryExpression"/>.</returns>
582 public static UnaryExpression IsFalse(Expression expression) {
583 return IsFalse(expression, null);
587 /// Returns whether the expression evaluates to false.
589 ///<param name="expression">An <see cref="T:System.Linq.Expressions.Expression" /> to evaluate.</param>
590 ///<param name="method">A <see cref="T:System.Reflection.MethodInfo" /> that represents the implementing method.</param>
591 /// <returns>An instance of <see cref="UnaryExpression"/>.</returns>
592 public static UnaryExpression IsFalse(Expression expression, MethodInfo method) {
593 RequiresCanRead(expression, "expression");
594 if (method == null) {
595 if (TypeUtils.IsBool(expression.Type)) {
596 return new UnaryExpression(ExpressionType.IsFalse, expression, expression.Type, null);
598 return GetUserDefinedUnaryOperatorOrThrow(ExpressionType.IsFalse, "op_False", expression);
600 return GetMethodBasedUnaryOperator(ExpressionType.IsFalse, expression, method);
604 /// Returns whether the expression evaluates to true.
606 /// <param name="expression">An <see cref="T:System.Linq.Expressions.Expression" /> to evaluate.</param>
607 /// <returns>An instance of <see cref="UnaryExpression"/>.</returns>
608 public static UnaryExpression IsTrue(Expression expression) {
609 return IsTrue(expression, null);
613 /// Returns whether the expression evaluates to true.
615 ///<param name="expression">An <see cref="T:System.Linq.Expressions.Expression" /> to evaluate.</param>
616 ///<param name="method">A <see cref="T:System.Reflection.MethodInfo" /> that represents the implementing method.</param>
617 /// <returns>An instance of <see cref="UnaryExpression"/>.</returns>
618 public static UnaryExpression IsTrue(Expression expression, MethodInfo method) {
619 RequiresCanRead(expression, "expression");
620 if (method == null) {
621 if (TypeUtils.IsBool(expression.Type)) {
622 return new UnaryExpression(ExpressionType.IsTrue, expression, expression.Type, null);
624 return GetUserDefinedUnaryOperatorOrThrow(ExpressionType.IsTrue, "op_True", expression);
626 return GetMethodBasedUnaryOperator(ExpressionType.IsTrue, expression, method);
630 /// Returns the expression representing the ones complement.
632 ///<param name="expression">An <see cref="T:System.Linq.Expressions.Expression" />.</param>
633 /// <returns>An instance of <see cref="UnaryExpression"/>.</returns>
634 public static UnaryExpression OnesComplement(Expression expression) {
635 return OnesComplement(expression, null);
639 /// Returns the expression representing the ones complement.
641 /// <param name="expression">An <see cref="T:System.Linq.Expressions.Expression" />.</param>
642 /// <param name="method">A <see cref="T:System.Reflection.MethodInfo" /> that represents the implementing method.</param>
643 /// <returns>An instance of <see cref="UnaryExpression"/>.</returns>
644 public static UnaryExpression OnesComplement(Expression expression, MethodInfo method) {
645 RequiresCanRead(expression, "expression");
646 if (method == null) {
647 if (TypeUtils.IsInteger(expression.Type)) {
648 return new UnaryExpression(ExpressionType.OnesComplement, expression, expression.Type, null);
650 return GetUserDefinedUnaryOperatorOrThrow(ExpressionType.OnesComplement, "op_OnesComplement", expression);
652 return GetMethodBasedUnaryOperator(ExpressionType.OnesComplement, expression, method);
655 ///<summary>Creates a <see cref="T:System.Linq.Expressions.UnaryExpression" /> that represents an explicit reference or boxing conversion where null is supplied if the conversion fails.</summary>
656 ///<returns>A <see cref="T:System.Linq.Expressions.UnaryExpression" /> that has the <see cref="P:System.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:System.Linq.Expressions.ExpressionType.TypeAs" /> and the <see cref="P:System.Linq.Expressions.UnaryExpression.Operand" /> and <see cref="P:System.Linq.Expressions.Expression.Type" /> properties set to the specified values.</returns>
657 ///<param name="expression">An <see cref="T:System.Linq.Expressions.Expression" /> to set the <see cref="P:System.Linq.Expressions.UnaryExpression.Operand" /> property equal to.</param>
658 ///<param name="type">A <see cref="T:System.Type" /> to set the <see cref="P:System.Linq.Expressions.Expression.Type" /> property equal to.</param>
659 ///<exception cref="T:System.ArgumentNullException">
660 ///<paramref name="expression" /> or <paramref name="type" /> is null.</exception>
661 public static UnaryExpression TypeAs(Expression expression, Type type) {
662 RequiresCanRead(expression, "expression");
663 ContractUtils.RequiresNotNull(type, "type");
664 TypeUtils.ValidateType(type);
666 if (type.IsValueType && !TypeUtils.IsNullableType(type)) {
667 throw Error.IncorrectTypeForTypeAs(type);
669 return new UnaryExpression(ExpressionType.TypeAs, expression, type, null);
673 /// <summary>Creates a <see cref="T:System.Linq.Expressions.UnaryExpression" /> that represents an explicit unboxing.</summary>
675 /// <param name="expression">An <see cref="T:System.Linq.Expressions.Expression" /> to unbox.</param>
676 /// <param name="type">The new <see cref="T:System.Type" /> of the expression.</param>
677 /// <returns>An instance of <see cref="UnaryExpression"/>.</returns>
678 public static UnaryExpression Unbox(Expression expression, Type type) {
679 RequiresCanRead(expression, "expression");
680 ContractUtils.RequiresNotNull(type, "type");
681 if (!expression.Type.IsInterface && expression.Type != typeof(object)) {
682 throw Error.InvalidUnboxType();
684 if (!type.IsValueType) throw Error.InvalidUnboxType();
685 TypeUtils.ValidateType(type);
686 return new UnaryExpression(ExpressionType.Unbox, expression, type, null);
689 ///<summary>Creates a <see cref="T:System.Linq.Expressions.UnaryExpression" /> that represents a conversion operation.</summary>
690 ///<returns>A <see cref="T:System.Linq.Expressions.UnaryExpression" /> that has the <see cref="P:System.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:System.Linq.Expressions.ExpressionType.Convert" /> and the <see cref="P:System.Linq.Expressions.UnaryExpression.Operand" /> and <see cref="P:System.Linq.Expressions.Expression.Type" /> properties set to the specified values.</returns>
691 ///<param name="expression">An <see cref="T:System.Linq.Expressions.Expression" /> to set the <see cref="P:System.Linq.Expressions.UnaryExpression.Operand" /> property equal to.</param>
692 ///<param name="type">A <see cref="T:System.Type" /> to set the <see cref="P:System.Linq.Expressions.Expression.Type" /> property equal to.</param>
693 ///<exception cref="T:System.ArgumentNullException">
694 ///<paramref name="expression" /> or <paramref name="type" /> is null.</exception>
695 ///<exception cref="T:System.InvalidOperationException">No conversion operator is defined between <paramref name="expression" />.Type and <paramref name="type" />.</exception>
696 public static UnaryExpression Convert(Expression expression, Type type) {
697 return Convert(expression, type, null);
700 ///<summary>Creates a <see cref="T:System.Linq.Expressions.UnaryExpression" /> that represents a conversion operation for which the implementing method is specified.</summary>
701 ///<returns>A <see cref="T:System.Linq.Expressions.UnaryExpression" /> that has the <see cref="P:System.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:System.Linq.Expressions.ExpressionType.Convert" /> and the <see cref="P:System.Linq.Expressions.UnaryExpression.Operand" />, <see cref="P:System.Linq.Expressions.Expression.Type" />, and <see cref="P:System.Linq.Expressions.UnaryExpression.Method" /> properties set to the specified values.</returns>
702 ///<param name="expression">An <see cref="T:System.Linq.Expressions.Expression" /> to set the <see cref="P:System.Linq.Expressions.UnaryExpression.Operand" /> property equal to.</param>
703 ///<param name="type">A <see cref="T:System.Type" /> to set the <see cref="P:System.Linq.Expressions.Expression.Type" /> property equal to.</param>
704 ///<param name="method">A <see cref="T:System.Reflection.MethodInfo" /> to set the <see cref="P:System.Linq.Expressions.UnaryExpression.Method" /> property equal to.</param>
705 ///<exception cref="T:System.ArgumentNullException">
706 ///<paramref name="expression" /> or <paramref name="type" /> is null.</exception>
707 ///<exception cref="T:System.ArgumentException">
708 ///<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>
709 ///<exception cref="T:System.Reflection.AmbiguousMatchException">More than one method that matches the <paramref name="method" /> description was found.</exception>
710 ///<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>
711 public static UnaryExpression Convert(Expression expression, Type type, MethodInfo method) {
712 RequiresCanRead(expression, "expression");
713 ContractUtils.RequiresNotNull(type, "type");
714 TypeUtils.ValidateType(type);
716 if (method == null) {
717 if (TypeUtils.HasIdentityPrimitiveOrNullableConversion(expression.Type, type) ||
718 TypeUtils.HasReferenceConversion(expression.Type, type)) {
719 return new UnaryExpression(ExpressionType.Convert, expression, type, null);
721 return GetUserDefinedCoercionOrThrow(ExpressionType.Convert, expression, type);
723 return GetMethodBasedCoercionOperator(ExpressionType.Convert, expression, type, method);
726 ///<summary>Creates a <see cref="T:System.Linq.Expressions.UnaryExpression" /> that represents a conversion operation that throws an exception if the target type is overflowed.</summary>
727 ///<returns>A <see cref="T:System.Linq.Expressions.UnaryExpression" /> that has the <see cref="P:System.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:System.Linq.Expressions.ExpressionType.ConvertChecked" /> and the <see cref="P:System.Linq.Expressions.UnaryExpression.Operand" /> and <see cref="P:System.Linq.Expressions.Expression.Type" /> properties set to the specified values.</returns>
728 ///<param name="expression">An <see cref="T:System.Linq.Expressions.Expression" /> to set the <see cref="P:System.Linq.Expressions.UnaryExpression.Operand" /> property equal to.</param>
729 ///<param name="type">A <see cref="T:System.Type" /> to set the <see cref="P:System.Linq.Expressions.Expression.Type" /> property equal to.</param>
730 ///<exception cref="T:System.ArgumentNullException">
731 ///<paramref name="expression" /> or <paramref name="type" /> is null.</exception>
732 ///<exception cref="T:System.InvalidOperationException">No conversion operator is defined between <paramref name="expression" />.Type and <paramref name="type" />.</exception>
733 public static UnaryExpression ConvertChecked(Expression expression, Type type) {
734 return ConvertChecked(expression, type, null);
737 ///<summary>Creates a <see cref="T:System.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>
738 ///<returns>A <see cref="T:System.Linq.Expressions.UnaryExpression" /> that has the <see cref="P:System.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:System.Linq.Expressions.ExpressionType.ConvertChecked" /> and the <see cref="P:System.Linq.Expressions.UnaryExpression.Operand" />, <see cref="P:System.Linq.Expressions.Expression.Type" />, and <see cref="P:System.Linq.Expressions.UnaryExpression.Method" /> properties set to the specified values.</returns>
739 ///<param name="expression">An <see cref="T:System.Linq.Expressions.Expression" /> to set the <see cref="P:System.Linq.Expressions.UnaryExpression.Operand" /> property equal to.</param>
740 ///<param name="type">A <see cref="T:System.Type" /> to set the <see cref="P:System.Linq.Expressions.Expression.Type" /> property equal to.</param>
741 ///<param name="method">A <see cref="T:System.Reflection.MethodInfo" /> to set the <see cref="P:System.Linq.Expressions.UnaryExpression.Method" /> property equal to.</param>
742 ///<exception cref="T:System.ArgumentNullException">
743 ///<paramref name="expression" /> or <paramref name="type" /> is null.</exception>
744 ///<exception cref="T:System.ArgumentException">
745 ///<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>
746 ///<exception cref="T:System.Reflection.AmbiguousMatchException">More than one method that matches the <paramref name="method" /> description was found.</exception>
747 ///<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>
748 public static UnaryExpression ConvertChecked(Expression expression, Type type, MethodInfo method) {
749 RequiresCanRead(expression, "expression");
750 ContractUtils.RequiresNotNull(type, "type");
751 TypeUtils.ValidateType(type);
753 if (method == null) {
754 if (TypeUtils.HasIdentityPrimitiveOrNullableConversion(expression.Type, type)) {
755 return new UnaryExpression(ExpressionType.ConvertChecked, expression, type, null);
757 if (TypeUtils.HasReferenceConversion(expression.Type, type)) {
758 return new UnaryExpression(ExpressionType.Convert, expression, type, null);
760 return GetUserDefinedCoercionOrThrow(ExpressionType.ConvertChecked, expression, type);
762 return GetMethodBasedCoercionOperator(ExpressionType.ConvertChecked, expression, type, method);
765 ///<summary>Creates a <see cref="T:System.Linq.Expressions.UnaryExpression" /> that represents getting the length of a one-dimensional array.</summary>
766 ///<returns>A <see cref="T:System.Linq.Expressions.UnaryExpression" /> that has the <see cref="P:System.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:System.Linq.Expressions.ExpressionType.ArrayLength" /> and the <see cref="P:System.Linq.Expressions.UnaryExpression.Operand" /> property equal to <paramref name="array" />.</returns>
767 ///<param name="array">An <see cref="T:System.Linq.Expressions.Expression" /> to set the <see cref="P:System.Linq.Expressions.UnaryExpression.Operand" /> property equal to.</param>
768 ///<exception cref="T:System.ArgumentNullException">
769 ///<paramref name="array" /> is null.</exception>
770 ///<exception cref="T:System.ArgumentException">
771 ///<paramref name="array" />.Type does not represent an array type.</exception>
772 public static UnaryExpression ArrayLength(Expression array) {
773 ContractUtils.RequiresNotNull(array, "array");
774 if (!array.Type.IsArray || !typeof(Array).IsAssignableFrom(array.Type)) {
775 throw Error.ArgumentMustBeArray();
777 if (array.Type.GetArrayRank() != 1) {
778 throw Error.ArgumentMustBeSingleDimensionalArrayType();
780 return new UnaryExpression(ExpressionType.ArrayLength, array, typeof(int), null);
783 ///<summary>Creates a <see cref="T:System.Linq.Expressions.UnaryExpression" /> that represents an expression that has a constant value of type <see cref="T:System.Linq.Expressions.Expression" />.</summary>
784 ///<returns>A <see cref="T:System.Linq.Expressions.UnaryExpression" /> that has the <see cref="P:System.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:System.Linq.Expressions.ExpressionType.Quote" /> and the <see cref="P:System.Linq.Expressions.UnaryExpression.Operand" /> property set to the specified value.</returns>
785 ///<param name="expression">An <see cref="T:System.Linq.Expressions.Expression" /> to set the <see cref="P:System.Linq.Expressions.UnaryExpression.Operand" /> property equal to.</param>
786 ///<exception cref="T:System.ArgumentNullException">
787 ///<paramref name="expression" /> is null.</exception>
788 public static UnaryExpression Quote(Expression expression) {
789 RequiresCanRead(expression, "expression");
790 bool validQuote = expression is LambdaExpression;
792 validQuote |= SilverlightQuirks;
794 if (!validQuote) throw Error.QuotedExpressionMustBeLambda();
795 return new UnaryExpression(ExpressionType.Quote, expression, expression.GetType(), null);
799 /// Creates a <see cref="T:System.Linq.Expressions.UnaryExpression" /> that represents a rethrowing of an exception.
801 /// <returns>A <see cref="T:System.Linq.Expressions.UnaryExpression"/> that represents a rethrowing of an exception.</returns>
802 public static UnaryExpression Rethrow() {
807 /// Creates a <see cref="T:System.Linq.Expressions.UnaryExpression" /> that represents a rethrowing of an exception with a given type.
809 ///<param name="type">The new <see cref="T:System.Type" /> of the expression.</param>
810 /// <returns>A <see cref="T:System.Linq.Expressions.UnaryExpression"/> that represents a rethrowing of an exception.</returns>
811 public static UnaryExpression Rethrow(Type type) {
812 return Throw(null, type);
816 /// Creates a <see cref="T:System.Linq.Expressions.UnaryExpression" /> that represents a throwing of an exception.
818 /// <param name="value">An <see cref="T:System.Linq.Expressions.Expression" />.</param>
819 /// <returns>A <see cref="T:System.Linq.Expressions.UnaryExpression"/> that represents the exception.</returns>
820 public static UnaryExpression Throw(Expression value) {
821 return Throw(value, typeof(void));
825 /// Creates a <see cref="T:System.Linq.Expressions.UnaryExpression" /> that represents a throwing of a value with a given type.
827 /// <param name="value">An <see cref="T:System.Linq.Expressions.Expression" />.</param>
828 /// <param name="type">The new <see cref="T:System.Type" /> of the expression.</param>
829 /// <returns>A <see cref="T:System.Linq.Expressions.UnaryExpression"/> that represents the exception.</returns>
830 public static UnaryExpression Throw(Expression value, Type type) {
831 ContractUtils.RequiresNotNull(type, "type");
832 TypeUtils.ValidateType(type);
835 RequiresCanRead(value, "value");
836 if (value.Type.IsValueType) throw Error.ArgumentMustNotHaveValueType();
838 return new UnaryExpression(ExpressionType.Throw, value, type, null);
842 /// Creates a <see cref="T:System.Linq.Expressions.UnaryExpression" /> that represents the incrementing of the expression by 1.
844 /// <param name="expression">An <see cref="T:System.Linq.Expressions.Expression"></see> to increment.</param>
845 /// <returns>A <see cref="T:System.Linq.Expressions.UnaryExpression"/> that represents the incremented expression.</returns>
846 public static UnaryExpression Increment(Expression expression) {
847 return Increment(expression, null);
851 /// Creates a <see cref="T:System.Linq.Expressions.UnaryExpression" /> that represents the incrementing of the expression by 1.
853 /// <param name="expression">An <see cref="T:System.Linq.Expressions.Expression"></see> to increment.</param>
854 ///<param name="method">A <see cref="T:System.Reflection.MethodInfo" /> that represents the implementing method.</param>
855 /// <returns>A <see cref="T:System.Linq.Expressions.UnaryExpression"/> that represents the incremented expression.</returns>
856 public static UnaryExpression Increment(Expression expression, MethodInfo method) {
857 RequiresCanRead(expression, "expression");
858 if (method == null) {
859 if (TypeUtils.IsArithmetic(expression.Type)) {
860 return new UnaryExpression(ExpressionType.Increment, expression, expression.Type, null);
862 return GetUserDefinedUnaryOperatorOrThrow(ExpressionType.Increment, "op_Increment", expression);
864 return GetMethodBasedUnaryOperator(ExpressionType.Increment, expression, method);
868 /// Creates a <see cref="T:System.Linq.Expressions.UnaryExpression" /> that represents the decrementing of the expression by 1.
870 /// <param name="expression">An <see cref="T:System.Linq.Expressions.Expression"></see> to decrement.</param>
871 /// <returns>A <see cref="T:System.Linq.Expressions.UnaryExpression"/> that represents the decremented expression.</returns>
872 public static UnaryExpression Decrement(Expression expression) {
873 return Decrement(expression, null);
877 /// Creates a <see cref="T:System.Linq.Expressions.UnaryExpression" /> that represents the decrementing of the expression by 1.
879 /// <param name="expression">An <see cref="T:System.Linq.Expressions.Expression"></see> to decrement.</param>
880 ///<param name="method">A <see cref="T:System.Reflection.MethodInfo" /> that represents the implementing method.</param>
881 /// <returns>A <see cref="T:System.Linq.Expressions.UnaryExpression"/> that represents the decremented expression.</returns>
882 public static UnaryExpression Decrement(Expression expression, MethodInfo method) {
883 RequiresCanRead(expression, "expression");
884 if (method == null) {
885 if (TypeUtils.IsArithmetic(expression.Type)) {
886 return new UnaryExpression(ExpressionType.Decrement, expression, expression.Type, null);
888 return GetUserDefinedUnaryOperatorOrThrow(ExpressionType.Decrement, "op_Decrement", expression);
890 return GetMethodBasedUnaryOperator(ExpressionType.Decrement, expression, method);
894 /// Creates a <see cref="UnaryExpression"/> that increments the expression by 1
895 /// and assigns the result back to the expression.
897 /// <param name="expression">An <see cref="T:System.Linq.Expressions.Expression"></see> to apply the operations on.</param>
898 /// <returns>A <see cref="T:System.Linq.Expressions.UnaryExpression"/> that represents the resultant expression.</returns>
899 public static UnaryExpression PreIncrementAssign(Expression expression) {
900 return MakeOpAssignUnary(ExpressionType.PreIncrementAssign, expression, null);
905 /// Creates a <see cref="UnaryExpression"/> that increments the expression by 1
906 /// and assigns the result back to the expression.
908 /// <param name="expression">An <see cref="T:System.Linq.Expressions.Expression"></see> to apply the operations on.</param>
909 /// <param name="method">A <see cref="T:System.Reflection.MethodInfo" /> that represents the implementing method.</param>
910 /// <returns>A <see cref="T:System.Linq.Expressions.UnaryExpression"/> that represents the resultant expression.</returns>
911 public static UnaryExpression PreIncrementAssign(Expression expression, MethodInfo method) {
912 return MakeOpAssignUnary(ExpressionType.PreIncrementAssign, expression, method);
916 /// Creates a <see cref="UnaryExpression"/> that decrements the expression by 1
917 /// and assigns the result back to the expression.
919 /// <param name="expression">An <see cref="T:System.Linq.Expressions.Expression"></see> to apply the operations on.</param>
920 /// <returns>A <see cref="T:System.Linq.Expressions.UnaryExpression"/> that represents the resultant expression.</returns>
921 public static UnaryExpression PreDecrementAssign(Expression expression) {
922 return MakeOpAssignUnary(ExpressionType.PreDecrementAssign, expression, null);
926 /// Creates a <see cref="UnaryExpression"/> that decrements the expression by 1
927 /// and assigns the result back to the expression.
929 /// <param name="expression">An <see cref="T:System.Linq.Expressions.Expression"></see> to apply the operations on.</param>
930 /// <param name="method">A <see cref="T:System.Reflection.MethodInfo" /> that represents the implementing method.</param>
931 /// <returns>A <see cref="T:System.Linq.Expressions.UnaryExpression"/> that represents the resultant expression.</returns>
932 public static UnaryExpression PreDecrementAssign(Expression expression, MethodInfo method) {
933 return MakeOpAssignUnary(ExpressionType.PreDecrementAssign, expression, method);
937 /// Creates a <see cref="UnaryExpression"/> that represents the assignment of the expression
938 /// followed by a subsequent increment by 1 of the original expression.
940 /// <param name="expression">An <see cref="T:System.Linq.Expressions.Expression"></see> to apply the operations on.</param>
941 /// <returns>A <see cref="T:System.Linq.Expressions.UnaryExpression"/> that represents the resultant expression.</returns>
942 public static UnaryExpression PostIncrementAssign(Expression expression) {
943 return MakeOpAssignUnary(ExpressionType.PostIncrementAssign, expression, null);
947 /// Creates a <see cref="UnaryExpression"/> that represents the assignment of the expression
948 /// followed by a subsequent increment by 1 of the original expression.
950 /// <param name="expression">An <see cref="T:System.Linq.Expressions.Expression"></see> to apply the operations on.</param>
951 /// <param name="method">A <see cref="T:System.Reflection.MethodInfo" /> that represents the implementing method.</param>
952 /// <returns>A <see cref="T:System.Linq.Expressions.UnaryExpression"/> that represents the resultant expression.</returns>
953 public static UnaryExpression PostIncrementAssign(Expression expression, MethodInfo method) {
954 return MakeOpAssignUnary(ExpressionType.PostIncrementAssign, expression, method);
958 /// Creates a <see cref="UnaryExpression"/> that represents the assignment of the expression
959 /// followed by a subsequent decrement by 1 of the original expression.
961 /// <param name="expression">An <see cref="T:System.Linq.Expressions.Expression"></see> to apply the operations on.</param>
962 /// <returns>A <see cref="T:System.Linq.Expressions.UnaryExpression"/> that represents the resultant expression.</returns>
963 public static UnaryExpression PostDecrementAssign(Expression expression) {
964 return MakeOpAssignUnary(ExpressionType.PostDecrementAssign, expression, null);
968 /// Creates a <see cref="UnaryExpression"/> that represents the assignment of the expression
969 /// followed by a subsequent decrement by 1 of the original expression.
971 /// <param name="expression">An <see cref="T:System.Linq.Expressions.Expression"></see> to apply the operations on.</param>
972 /// <param name="method">A <see cref="T:System.Reflection.MethodInfo" /> that represents the implementing method.</param>
973 /// <returns>A <see cref="T:System.Linq.Expressions.UnaryExpression"/> that represents the resultant expression.</returns>
974 public static UnaryExpression PostDecrementAssign(Expression expression, MethodInfo method) {
975 return MakeOpAssignUnary(ExpressionType.PostDecrementAssign, expression, method);
978 private static UnaryExpression MakeOpAssignUnary(ExpressionType kind, Expression expression, MethodInfo method) {
979 RequiresCanRead(expression, "expression");
980 RequiresCanWrite(expression, "expression");
982 UnaryExpression result;
983 if (method == null) {
984 if (TypeUtils.IsArithmetic(expression.Type)) {
985 return new UnaryExpression(kind, expression, expression.Type, null);
988 if (kind == ExpressionType.PreIncrementAssign || kind == ExpressionType.PostIncrementAssign) {
989 name = "op_Increment";
991 name = "op_Decrement";
993 result = GetUserDefinedUnaryOperatorOrThrow(kind, name, expression);
995 result = GetMethodBasedUnaryOperator(kind, expression, method);
997 // return type must be assignable back to the operand type
998 if (!TypeUtils.AreReferenceAssignable(expression.Type, result.Type)) {
999 throw Error.UserDefinedOpMustHaveValidReturnType(kind, method.Name);