BindingFlags.Public needed here as Exception.HResult is now public in .NET 4.5. This...
[mono.git] / mcs / class / dlr / Runtime / Microsoft.Scripting.Core / Ast / UnaryExpression.cs
1 /* ****************************************************************************
2  *
3  * Copyright (c) Microsoft Corporation. 
4  *
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.
10  *
11  * You must not remove this notice, or any other, from this software.
12  *
13  *
14  * ***************************************************************************/
15
16 using System;
17 using System.Diagnostics;
18 using System.Dynamic.Utils;
19 using System.Reflection;
20 using System.Runtime.CompilerServices;
21
22 #if SILVERLIGHT
23 using System.Core;
24 #endif
25
26 #if CLR2
27 namespace Microsoft.Scripting.Ast {
28 #else
29 namespace System.Linq.Expressions {
30 #endif
31
32     /// <summary>
33     /// Represents an expression that has a unary operator.
34     /// </summary>
35 #if !SILVERLIGHT
36     [DebuggerTypeProxy(typeof(Expression.UnaryExpressionProxy))]
37 #endif
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;
43
44         internal UnaryExpression(ExpressionType nodeType, Expression expression, Type type, MethodInfo method) {
45             _operand = expression;
46             _method = method;
47             _nodeType = nodeType;
48             _type = type;
49         }
50
51         /// <summary>
52         /// Gets the static type of the expression that this <see cref="Expression" /> represents. (Inherited from <see cref="Expression"/>.)
53         /// </summary>
54         /// <returns>The <see cref="Type"/> that represents the static type of the expression.</returns>
55         public sealed override Type Type {
56             get { return _type; }
57         }
58
59         /// <summary>
60         /// Returns the node type of this <see cref="Expression" />. (Inherited from <see cref="Expression" />.)
61         /// </summary>
62         /// <returns>The <see cref="ExpressionType"/> that represents this expression.</returns>
63         public sealed override ExpressionType NodeType {
64             get { return _nodeType; }
65         }
66
67         /// <summary>
68         /// Gets the operand of the unary operation.
69         /// </summary>
70         /// <returns> An <see cref="ExpressionType"/> that represents the operand of the unary operation.</returns>
71         public Expression Operand {
72             get { return _operand; }
73         }
74
75         /// <summary>
76         /// Gets the implementing method for the unary operation.
77         /// </summary>
78         /// <returns>The <see cref="MethodInfo"/> that represents the implementing method.</returns>
79         public MethodInfo Method {
80             get { return _method; }
81         }
82
83         /// <summary>
84         /// Gets a value that indicates whether the expression tree node represents a lifted call to an operator.
85         /// </summary>
86         /// <returns>true if the node represents a lifted call; otherwise, false.</returns>
87         public bool IsLifted {
88             get {
89                 if (NodeType == ExpressionType.TypeAs || NodeType == ExpressionType.Quote || NodeType == ExpressionType.Throw) {
90                     return false;
91                 }
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));
97                 }
98                 return operandIsNullable || resultIsNullable;
99             }
100         }
101
102         /// <summary>
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.
104         /// </summary>
105         /// <returns>true if the operator's return type is lifted to a nullable type; otherwise, false.</returns>
106         public bool IsLiftedToNull {
107             get {
108                 return IsLifted && TypeUtils.IsNullableType(this.Type);
109             }
110         }
111
112         /// <summary>
113         /// Dispatches to the specific visit method for this node type.
114         /// </summary>
115         protected internal override Expression Accept(ExpressionVisitor visitor) {
116             return visitor.VisitUnary(this);
117         }
118
119         /// <summary>
120         /// Gets a value that indicates whether the expression tree node can be reduced. 
121         /// </summary>        
122         public override bool CanReduce {
123             get {
124                 switch (_nodeType) {
125                     case ExpressionType.PreIncrementAssign:
126                     case ExpressionType.PreDecrementAssign:
127                     case ExpressionType.PostIncrementAssign:
128                     case ExpressionType.PostDecrementAssign:
129                         return true;
130                 }
131                 return false;
132             }
133         }
134
135         /// <summary>
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 
139         /// must be reduced.
140         /// </summary>
141         /// <returns>The reduced expression.</returns>
142         public override Expression Reduce() {
143             if (CanReduce) {
144                 switch (_operand.NodeType) {
145                     case ExpressionType.Index:
146                         return ReduceIndex();
147                     case ExpressionType.MemberAccess:
148                         return ReduceMember();
149                     default:
150                         return ReduceVariable();
151                 }
152             }
153             return this;
154         }
155
156         private bool IsPrefix {
157             get { return _nodeType == ExpressionType.PreIncrementAssign || _nodeType == ExpressionType.PreDecrementAssign; }
158         }
159
160         private UnaryExpression FunctionalOp(Expression operand) {
161             ExpressionType functional;
162             if (_nodeType == ExpressionType.PreIncrementAssign || _nodeType == ExpressionType.PostIncrementAssign) {
163                 functional = ExpressionType.Increment;
164             } else {
165                 functional = ExpressionType.Decrement;
166             }
167             return new UnaryExpression(functional, operand, operand.Type, _method);
168         }
169
170         private Expression ReduceVariable() {
171             if (IsPrefix) {
172                 // (op) var
173                 // ... is reduced into ...
174                 // var = op(var)
175                 return Assign(_operand, FunctionalOp(_operand));
176             }
177             // var (op)
178             // ... is reduced into ...
179             // temp = var
180             // var = op(var)
181             // temp
182             var temp = Parameter(_operand.Type, null);
183             return Block(
184                 new[] { temp },
185                 Assign(temp, _operand),
186                 Assign(_operand, FunctionalOp(temp)),
187                 temp
188             );
189         }
190
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();
196             } else {
197                 var temp1 = Parameter(member.Expression.Type, null);
198                 var initTemp1 = Assign(temp1, member.Expression);
199                 member = MakeMemberAccess(temp1, member.Member);
200
201                 if (IsPrefix) {
202                     // (op) value.member
203                     // ... is reduced into ...
204                     // temp1 = value
205                     // temp1.member = op(temp1.member)
206                     return Block(
207                         new[] { temp1 },
208                         initTemp1,
209                         Assign(member, FunctionalOp(member))
210                     );
211                 }
212
213                 // value.member (op)
214                 // ... is reduced into ...
215                 // temp1 = value
216                 // temp2 = temp1.member
217                 // temp1.member = op(temp2)
218                 // temp2
219                 var temp2 = Parameter(member.Type, null);
220                 return Block(
221                     new[] { temp1, temp2 },
222                     initTemp1,
223                     Assign(temp2, member),
224                     Assign(member, FunctionalOp(temp2)),
225                     temp2
226                 );
227             }
228         }
229
230         private Expression ReduceIndex() {
231             // left[a0, a1, ... aN] (op)
232             //
233             // ... is reduced into ...
234             //
235             // tempObj = left
236             // tempArg0 = a0
237             // ...
238             // tempArgN = aN
239             // tempValue = tempObj[tempArg0, ... tempArgN]
240             // tempObj[tempArg0, ... tempArgN] = op(tempValue)
241             // tempValue
242
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];
249
250             int i = 0;
251             temps[i] = Parameter(index.Object.Type, null);
252             block[i] = Assign(temps[i], index.Object);
253             i++;
254             while (i <= count) {
255                 var arg = index.Arguments[i - 1];
256                 args[i - 1] = temps[i] = Parameter(arg.Type, null);
257                 block[i] = Assign(temps[i], arg);
258                 i++;
259             }
260             index = MakeIndex(temps[0], index.Indexer, new TrueReadOnlyCollection<Expression>(args));
261             if (!prefix) {
262                 var lastTemp = temps[i] = Parameter(index.Type, null);
263                 block[i] = Assign(temps[i], index);
264                 i++;
265                 Debug.Assert(i == temps.Length);
266                 block[i++] = Assign(index, FunctionalOp(lastTemp));
267                 block[i++] = lastTemp;
268             } else {
269                 Debug.Assert(i == temps.Length);
270                 block[i++] = Assign(index, FunctionalOp(index));
271             }
272             Debug.Assert(i == block.Length);
273             return Block(new TrueReadOnlyCollection<ParameterExpression>(temps), new TrueReadOnlyCollection<Expression>(block));
274         }
275
276         /// <summary>
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.
280         /// </summary>
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) {
285                 return this;
286             }
287             return Expression.MakeUnary(NodeType, operand, Type, Method);
288         }
289     }
290
291     public partial class Expression {
292
293         /// <summary>
294         /// Creates a <see cref="UnaryExpression"></see>, given an operand, by calling the appropriate factory method.
295         /// </summary>
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);
304         }
305
306         /// <summary>
307         /// Creates a <see cref="UnaryExpression"></see>, given an operand and implementing method, by calling the appropriate factory method.
308         /// </summary>
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) {
318             switch (unaryType) {
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);
359                 default:
360                     throw Error.UnhandledUnary(unaryType);
361             }
362         }
363
364         private static UnaryExpression GetUserDefinedUnaryOperatorOrThrow(ExpressionType unaryType, string name, Expression operand) {
365             UnaryExpression u = GetUserDefinedUnaryOperator(unaryType, name, operand);
366             if (u != null) {
367                 ValidateParamswithOperandsOrThrow(u.Method.GetParametersCached()[0].ParameterType, operand.Type, unaryType, name);
368                 return u;
369             }
370             throw Error.UnaryOperatorNotDefined(unaryType, operand.Type);
371         }
372
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);
381             }
382             // try lifted call
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);
388                 }
389             }
390             return null;
391         }
392
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();
397             if (pms.Length != 1)
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);
402             }
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);
408             }
409
410             throw Error.OperandTypesDoNotMatchParameters(unaryType, method.Name);
411         }
412
413         private static UnaryExpression GetUserDefinedCoercionOrThrow(ExpressionType coercionType, Expression expression, Type convertToType) {
414             UnaryExpression u = GetUserDefinedCoercion(coercionType, expression, convertToType);
415             if (u != null) {
416                 return u;
417             }
418             throw Error.CoercionOperatorNotDefined(expression.Type, convertToType);
419         }
420
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);
425             } else {
426                 return null;
427             }
428         }
429
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);
436             }
437             if (ParameterIsAssignable(pms[0], operand.Type) && TypeUtils.AreEquivalent(method.ReturnType, convertToType)) {
438                 return new UnaryExpression(unaryType, operand, method.ReturnType, method);
439             }
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);
445             }
446             throw Error.OperandTypesDoNotMatchParameters(unaryType, method.Name);
447         }
448
449         /// <summary>
450         /// Creates a <see cref="UnaryExpression"></see> that represents an arithmetic negation operation.
451         /// </summary>
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);
458         }
459
460         /// <summary>
461         /// Creates a <see cref="UnaryExpression"></see> that represents an arithmetic negation operation.
462         /// </summary>
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);
474                 }
475                 return GetUserDefinedUnaryOperatorOrThrow(ExpressionType.Negate, "op_UnaryNegation", expression);
476             }
477             return GetMethodBasedUnaryOperator(ExpressionType.Negate, expression, method);
478         }
479
480         /// <summary>
481         /// Creates a <see cref="UnaryExpression"></see> that represents a unary plus operation.
482         /// </summary>
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);
489         }
490
491         /// <summary>
492         /// Creates a <see cref="UnaryExpression"></see> that represents a unary plus operation.
493         /// </summary>
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);
505                 }
506                 return GetUserDefinedUnaryOperatorOrThrow(ExpressionType.UnaryPlus, "op_UnaryPlus", expression);
507             }
508             return GetMethodBasedUnaryOperator(ExpressionType.UnaryPlus, expression, method);
509         }
510
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);
519         }
520
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);
536                 }
537                 return GetUserDefinedUnaryOperatorOrThrow(ExpressionType.NegateChecked, "op_UnaryNegation", expression);
538             }
539             return GetMethodBasedUnaryOperator(ExpressionType.NegateChecked, expression, method);
540         }
541
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);
550         }
551
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);
567                 }
568                 UnaryExpression u = GetUserDefinedUnaryOperator(ExpressionType.Not, "op_LogicalNot", expression);
569                 if (u != null) {
570                     return u;
571                 }
572                 return GetUserDefinedUnaryOperatorOrThrow(ExpressionType.Not, "op_OnesComplement", expression);
573             }
574             return GetMethodBasedUnaryOperator(ExpressionType.Not, expression, method);
575         }
576
577         /// <summary>
578         /// Returns whether the expression evaluates to false.
579         /// </summary>
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);
584         }
585
586         /// <summary>
587         /// Returns whether the expression evaluates to false.
588         /// </summary>
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);
597                 }
598                 return GetUserDefinedUnaryOperatorOrThrow(ExpressionType.IsFalse, "op_False", expression);
599             }
600             return GetMethodBasedUnaryOperator(ExpressionType.IsFalse, expression, method);
601         }
602
603         /// <summary>
604         /// Returns whether the expression evaluates to true.
605         /// </summary>
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);
610         }
611
612         /// <summary>
613         /// Returns whether the expression evaluates to true.
614         /// </summary>
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);
623                 }
624                 return GetUserDefinedUnaryOperatorOrThrow(ExpressionType.IsTrue, "op_True", expression);
625             }
626             return GetMethodBasedUnaryOperator(ExpressionType.IsTrue, expression, method);
627         }
628
629         /// <summary>
630         /// Returns the expression representing the ones complement.
631         /// </summary>
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);
636         }
637
638         /// <summary>
639         /// Returns the expression representing the ones complement.
640         /// </summary>
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);
649                 }
650                 return GetUserDefinedUnaryOperatorOrThrow(ExpressionType.OnesComplement, "op_OnesComplement", expression);
651             }
652             return GetMethodBasedUnaryOperator(ExpressionType.OnesComplement, expression, method);
653         }
654
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);
665
666             if (type.IsValueType && !TypeUtils.IsNullableType(type)) {
667                 throw Error.IncorrectTypeForTypeAs(type);
668             }
669             return new UnaryExpression(ExpressionType.TypeAs, expression, type, null);
670         }
671
672         /// <summary>
673         /// <summary>Creates a <see cref="T:System.Linq.Expressions.UnaryExpression" /> that represents an explicit unboxing.</summary>
674         /// </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();
683             }
684             if (!type.IsValueType) throw Error.InvalidUnboxType();
685             TypeUtils.ValidateType(type);
686             return new UnaryExpression(ExpressionType.Unbox, expression, type, null);
687         }
688
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);
698         }
699
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);
715
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);
720                 }
721                 return GetUserDefinedCoercionOrThrow(ExpressionType.Convert, expression, type);
722             }
723             return GetMethodBasedCoercionOperator(ExpressionType.Convert, expression, type, method);
724         }
725
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);
735         }
736
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);
752
753             if (method == null) {
754                 if (TypeUtils.HasIdentityPrimitiveOrNullableConversion(expression.Type, type)) {
755                     return new UnaryExpression(ExpressionType.ConvertChecked, expression, type, null);
756                 }
757                 if (TypeUtils.HasReferenceConversion(expression.Type, type)) {
758                     return new UnaryExpression(ExpressionType.Convert, expression, type, null);
759                 }
760                 return GetUserDefinedCoercionOrThrow(ExpressionType.ConvertChecked, expression, type);
761             }
762             return GetMethodBasedCoercionOperator(ExpressionType.ConvertChecked, expression, type, method);
763         }
764
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();
776             }
777             if (array.Type.GetArrayRank() != 1) {
778                 throw Error.ArgumentMustBeSingleDimensionalArrayType();
779             }
780             return new UnaryExpression(ExpressionType.ArrayLength, array, typeof(int), null);
781         }
782
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;
791 #if SILVERLIGHT
792             validQuote |= SilverlightQuirks;
793 #endif
794             if (!validQuote) throw Error.QuotedExpressionMustBeLambda();
795             return new UnaryExpression(ExpressionType.Quote, expression, expression.GetType(), null);
796         }
797
798         /// <summary>
799         /// Creates a <see cref="T:System.Linq.Expressions.UnaryExpression" /> that represents a rethrowing of an exception.
800         /// </summary>
801         /// <returns>A <see cref="T:System.Linq.Expressions.UnaryExpression"/> that represents a rethrowing of an exception.</returns>
802         public static UnaryExpression Rethrow() {
803             return Throw(null);
804         }
805
806         /// <summary>
807         /// Creates a <see cref="T:System.Linq.Expressions.UnaryExpression" /> that represents a rethrowing of an exception with a given type.
808         /// </summary>
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);
813         }
814
815         /// <summary>
816         /// Creates a <see cref="T:System.Linq.Expressions.UnaryExpression" /> that represents a throwing of an exception.
817         /// </summary>
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));
822         }
823
824         /// <summary>
825         /// Creates a <see cref="T:System.Linq.Expressions.UnaryExpression" /> that represents a throwing of a value with a given type.
826         /// </summary>
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);
833
834             if (value != null) {
835                 RequiresCanRead(value, "value");
836                 if (value.Type.IsValueType) throw Error.ArgumentMustNotHaveValueType();
837             }
838             return new UnaryExpression(ExpressionType.Throw, value, type, null);
839         }
840
841         /// <summary>
842         /// Creates a <see cref="T:System.Linq.Expressions.UnaryExpression" /> that represents the incrementing of the expression by 1.
843         /// </summary>
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);
848         }
849
850         /// <summary>
851         /// Creates a <see cref="T:System.Linq.Expressions.UnaryExpression" /> that represents the incrementing of the expression by 1.
852         /// </summary>
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);
861                 }
862                 return GetUserDefinedUnaryOperatorOrThrow(ExpressionType.Increment, "op_Increment", expression);
863             }
864             return GetMethodBasedUnaryOperator(ExpressionType.Increment, expression, method);
865         }
866
867         /// <summary>
868         /// Creates a <see cref="T:System.Linq.Expressions.UnaryExpression" /> that represents the decrementing of the expression by 1.
869         /// </summary>
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);
874         }
875
876         /// <summary>
877         /// Creates a <see cref="T:System.Linq.Expressions.UnaryExpression" /> that represents the decrementing of the expression by 1.
878         /// </summary>
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);
887                 }
888                 return GetUserDefinedUnaryOperatorOrThrow(ExpressionType.Decrement, "op_Decrement", expression);
889             }
890             return GetMethodBasedUnaryOperator(ExpressionType.Decrement, expression, method);
891         }
892
893         /// <summary>
894         /// Creates a <see cref="UnaryExpression"/> that increments the expression by 1
895         /// and assigns the result back to the expression.
896         /// </summary>
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);
901
902         }
903
904         /// <summary>
905         /// Creates a <see cref="UnaryExpression"/> that increments the expression by 1
906         /// and assigns the result back to the expression.
907         /// </summary>
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);
913         }
914
915         /// <summary>
916         /// Creates a <see cref="UnaryExpression"/> that decrements the expression by 1
917         /// and assigns the result back to the expression.
918         /// </summary>
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);
923         }
924
925         /// <summary>
926         /// Creates a <see cref="UnaryExpression"/> that decrements the expression by 1
927         /// and assigns the result back to the expression.
928         /// </summary>
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);
934         }
935
936         /// <summary>
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.
939         /// </summary>
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);
944         }
945
946         /// <summary>
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.
949         /// </summary>
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);
955         }
956
957         /// <summary>
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.
960         /// </summary>
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);
965         }
966
967         /// <summary>
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.
970         /// </summary>
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);
976         }
977
978         private static UnaryExpression MakeOpAssignUnary(ExpressionType kind, Expression expression, MethodInfo method) {
979             RequiresCanRead(expression, "expression");
980             RequiresCanWrite(expression, "expression");
981
982             UnaryExpression result;
983             if (method == null) {
984                 if (TypeUtils.IsArithmetic(expression.Type)) {
985                     return new UnaryExpression(kind, expression, expression.Type, null);
986                 }
987                 string name;
988                 if (kind == ExpressionType.PreIncrementAssign || kind == ExpressionType.PostIncrementAssign) {
989                     name = "op_Increment";
990                 } else {
991                     name = "op_Decrement";
992                 }
993                 result = GetUserDefinedUnaryOperatorOrThrow(kind, name, expression);
994             } else {
995                 result = GetMethodBasedUnaryOperator(kind, expression, method);
996             }
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);
1000             }
1001             return result;
1002         }
1003     }
1004 }