2009-07-11 Michael Barker <mike@middlesoft.co.uk>
[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 Microsoft Public License. A 
6  * copy of the license can be found in the License.html file at the root of this distribution. If 
7  * you cannot locate the  Microsoft Public License, please send an email to 
8  * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound 
9  * by the terms of the Microsoft Public License.
10  *
11  * You must not remove this notice, or any other, from this software.
12  *
13  *
14  * ***************************************************************************/
15 using System; using Microsoft;
16
17
18 using System.Diagnostics;
19 #if CODEPLEX_40
20 using System.Dynamic.Utils;
21 #else
22 using Microsoft.Scripting.Utils;
23 #endif
24 using System.Reflection;
25 using System.Runtime.CompilerServices;
26 #if !CODEPLEX_40
27 using Microsoft.Runtime.CompilerServices;
28 #endif
29
30
31 #if CODEPLEX_40
32 namespace System.Linq.Expressions {
33 #else
34 namespace Microsoft.Linq.Expressions {
35 #endif
36
37     /// <summary>
38     /// Represents an expression that has a unary operator.
39     /// </summary>
40 #if !SILVERLIGHT
41     [DebuggerTypeProxy(typeof(Expression.UnaryExpressionProxy))]
42 #endif
43     public sealed class UnaryExpression : Expression {
44         private readonly Expression _operand;
45         private readonly MethodInfo _method;
46         private readonly ExpressionType _nodeType;
47         private readonly Type _type;
48
49         internal UnaryExpression(ExpressionType nodeType, Expression expression, Type type, MethodInfo method) {
50             _operand = expression;
51             _method = method;
52             _nodeType = nodeType;
53             _type = type;
54         }
55
56         /// <summary>
57         /// Gets the static type of the expression that this <see cref="Expression" /> represents. (Inherited from <see cref="Expression"/>.)
58         /// </summary>
59         /// <returns>The <see cref="Type"/> that represents the static type of the expression.</returns>
60         public sealed override Type Type {
61             get { return _type; }
62         }
63
64         /// <summary>
65         /// Returns the node type of this <see cref="Expression" />. (Inherited from <see cref="Expression" />.)
66         /// </summary>
67         /// <returns>The <see cref="ExpressionType"/> that represents this expression.</returns>
68         public sealed override ExpressionType NodeType {
69             get { return _nodeType; }
70         }
71
72         /// <summary>
73         /// Gets the operand of the unary operation.
74         /// </summary>
75         /// <returns> An <see cref="ExpressionType"/> that represents the operand of the unary operation.</returns>
76         public Expression Operand {
77             get { return _operand; }
78         }
79
80         /// <summary>
81         /// Gets the implementing method for the unary operation.
82         /// </summary>
83         /// <returns>The <see cref="MethodInfo"/> that represents the implementing method.</returns>
84         public MethodInfo Method {
85             get { return _method; }
86         }
87
88         /// <summary>
89         /// Gets a value that indicates whether the expression tree node represents a lifted call to an operator.
90         /// </summary>
91         /// <returns>true if the node represents a lifted call; otherwise, false.</returns>
92         public bool IsLifted {
93             get {
94                 if (NodeType == ExpressionType.TypeAs || NodeType == ExpressionType.Quote || NodeType == ExpressionType.Throw) {
95                     return false;
96                 }
97                 bool operandIsNullable = TypeUtils.IsNullableType(_operand.Type);
98                 bool resultIsNullable = TypeUtils.IsNullableType(this.Type);
99                 if (_method != null) {
100                     return (operandIsNullable && !TypeUtils.AreEquivalent(_method.GetParametersCached()[0].ParameterType, _operand.Type)) ||
101                            (resultIsNullable && !TypeUtils.AreEquivalent(_method.ReturnType, this.Type));
102                 }
103                 return operandIsNullable || resultIsNullable;
104             }
105         }
106
107         /// <summary>
108         /// Gets a value that indicates whether the expression tree node represents a lifted call to an operator whose return type is lifted to a nullable type.
109         /// </summary>
110         /// <returns>true if the operator's return type is lifted to a nullable type; otherwise, false.</returns>
111         public bool IsLiftedToNull {
112             get {
113                 return IsLifted && TypeUtils.IsNullableType(this.Type);
114             }
115         }
116
117         internal override Expression Accept(ExpressionVisitor visitor) {
118             return visitor.VisitUnary(this);
119         }
120
121         /// <summary>
122         /// Gets a value that indicates whether the expression tree node can be reduced. 
123         /// </summary>        
124         public override bool CanReduce {
125             get {
126                 switch (_nodeType) {
127                     case ExpressionType.PreIncrementAssign:
128                     case ExpressionType.PreDecrementAssign:
129                     case ExpressionType.PostIncrementAssign:
130                     case ExpressionType.PostDecrementAssign:
131                         return true;
132                 }
133                 return false;
134             }
135         }
136
137         /// <summary>
138         /// Reduces the expression node to a simpler expression. 
139         /// If CanReduce returns true, this should return a valid expression.
140         /// This method is allowed to return another node which itself 
141         /// must be reduced.
142         /// </summary>
143         /// <returns>The reduced expression.</returns>
144         public override Expression Reduce() {
145             if (CanReduce) {
146                 switch (_operand.NodeType) {
147                     case ExpressionType.Index:
148                         return ReduceIndex();
149                     case ExpressionType.MemberAccess:
150                         return ReduceMember();
151                     default:
152                         return ReduceVariable();
153                 }
154             }
155             return this;
156         }
157
158         private bool IsPrefix {
159             get { return _nodeType == ExpressionType.PreIncrementAssign || _nodeType == ExpressionType.PreDecrementAssign; }
160         }
161
162         private UnaryExpression FunctionalOp(Expression operand) {
163             ExpressionType functional;
164             if (_nodeType == ExpressionType.PreIncrementAssign || _nodeType == ExpressionType.PostIncrementAssign) {
165                 functional = ExpressionType.Increment;
166             } else {
167                 functional = ExpressionType.Decrement;
168             }
169             return new UnaryExpression(functional, operand, operand.Type, _method);
170         }
171
172         private Expression ReduceVariable() {
173             if (IsPrefix) {
174                 // (op) var
175                 // ... is reduced into ...
176                 // var = op(var)
177                 return Assign(_operand, FunctionalOp(_operand));
178             }
179             // var (op)
180             // ... is reduced into ...
181             // temp = var
182             // var = op(var)
183             // temp
184             var temp = Parameter(_operand.Type, null);
185             return Block(
186                 new[] { temp },
187                 Assign(temp, _operand),
188                 Assign(_operand, FunctionalOp(temp)),
189                 temp
190             );
191         }
192
193         private Expression ReduceMember() {
194             var member = (MemberExpression)_operand;
195             if (member.Expression == null) {
196                 //static member, reduce the same as variable
197                 return ReduceVariable();
198             } else {
199                 var temp1 = Parameter(member.Expression.Type, null);
200                 var initTemp1 = Assign(temp1, member.Expression);
201                 member = MakeMemberAccess(temp1, member.Member);
202
203                 if (IsPrefix) {
204                     // (op) value.member
205                     // ... is reduced into ...
206                     // temp1 = value
207                     // temp1.member = op(temp1.member)
208                     return Block(
209                         new[] { temp1 },
210                         initTemp1,
211                         Assign(member, FunctionalOp(member))
212                     );
213                 }
214
215                 // value.member (op)
216                 // ... is reduced into ...
217                 // temp1 = value
218                 // temp2 = temp1.member
219                 // temp1.member = op(temp2)
220                 // temp2
221                 var temp2 = Parameter(member.Type, null);
222                 return Block(
223                     new[] { temp1, temp2 },
224                     initTemp1,
225                     Assign(temp2, member),
226                     Assign(member, FunctionalOp(temp2)),
227                     temp2
228                 );
229             }
230         }
231
232         private Expression ReduceIndex() {
233             // left[a0, a1, ... aN] (op)
234             //
235             // ... is reduced into ...
236             //
237             // tempObj = left
238             // tempArg0 = a0
239             // ...
240             // tempArgN = aN
241             // tempValue = tempObj[tempArg0, ... tempArgN]
242             // tempObj[tempArg0, ... tempArgN] = op(tempValue)
243             // tempValue
244
245             bool prefix = IsPrefix;
246             var index = (IndexExpression)_operand;
247             int count = index.Arguments.Count;
248             var block = new Expression[count + (prefix ? 2 : 4)];
249             var temps = new ParameterExpression[count + (prefix ? 1 : 2)];
250             var args = new ParameterExpression[count];
251
252             int i = 0;
253             temps[i] = Parameter(index.Object.Type, null);
254             block[i] = Assign(temps[i], index.Object);
255             i++;
256             while (i <= count) {
257                 var arg = index.Arguments[i - 1];
258                 args[i - 1] = temps[i] = Parameter(arg.Type, null);
259                 block[i] = Assign(temps[i], arg);
260                 i++;
261             }
262             index = MakeIndex(temps[0], index.Indexer, new TrueReadOnlyCollection<Expression>(args));
263             if (!prefix) {
264                 var lastTemp = temps[i] = Parameter(index.Type, null);
265                 block[i] = Assign(temps[i], index);
266                 i++;
267                 Debug.Assert(i == temps.Length);
268                 block[i++] = Assign(index, FunctionalOp(lastTemp));
269                 block[i++] = lastTemp;
270             } else {
271                 Debug.Assert(i == temps.Length);
272                 block[i++] = Assign(index, FunctionalOp(index));
273             }
274             Debug.Assert(i == block.Length);
275             return Block(new TrueReadOnlyCollection<ParameterExpression>(temps), new TrueReadOnlyCollection<Expression>(block));
276         }
277     }
278
279     public partial class Expression {
280
281         /// <summary>
282         /// Creates a <see cref="UnaryExpression"></see>, given an operand, by calling the appropriate factory method.
283         /// </summary>
284         /// <param name="unaryType">The <see cref="ExpressionType"></see> that specifies the type of unary operation.</param>
285         /// <param name="operand">An <see cref="Expression"></see> that represents the operand.</param>
286         /// <param name="type">The <see cref="Type"></see> that specifies the type to be converted to (pass null if not applicable).</param>
287         /// <returns>The <see cref="UnaryExpression"></see> that results from calling the appropriate factory method.</returns>
288         /// <exception cref="ArgumentException">Thrown when <paramref name="unaryType"/> does not correspond to a unary expression.</exception>
289         /// <exception cref="ArgumentNullException">Thrown when <paramref name="operand"/> is null.</exception>
290         public static UnaryExpression MakeUnary(ExpressionType unaryType, Expression operand, Type type) {
291             return MakeUnary(unaryType, operand, type, null);
292         }
293
294         /// <summary>
295         /// Creates a <see cref="UnaryExpression"></see>, given an operand and implementing method, by calling the appropriate factory method.
296         /// </summary>
297         /// <param name="unaryType">The <see cref="ExpressionType"></see> that specifies the type of unary operation.</param>
298         /// <param name="operand">An <see cref="Expression"></see> that represents the operand.</param>
299         /// <param name="type">The <see cref="Type"></see> that specifies the type to be converted to (pass null if not applicable).</param>
300         /// <param name="method">The <see cref="MethodInfo"></see> that represents the implementing method.</param>
301         /// <returns>The <see cref="UnaryExpression"></see> that results from calling the appropriate factory method.</returns>
302         /// <exception cref="ArgumentException">Thrown when <paramref name="unaryType"/> does not correspond to a unary expression.</exception> 
303         /// <exception cref="ArgumentNullException">Thrown when <paramref name="operand"/> is null.</exception>
304         [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
305         public static UnaryExpression MakeUnary(ExpressionType unaryType, Expression operand, Type type, MethodInfo method) {
306             switch (unaryType) {
307                 case ExpressionType.Negate:
308                     return Negate(operand, method);
309                 case ExpressionType.NegateChecked:
310                     return NegateChecked(operand, method);
311                 case ExpressionType.Not:
312                     return Not(operand, method);
313                 case ExpressionType.IsFalse:
314                     return IsFalse(operand, method);
315                 case ExpressionType.IsTrue:
316                     return IsTrue(operand, method);
317                 case ExpressionType.OnesComplement:
318                     return OnesComplement(operand, method);
319                 case ExpressionType.ArrayLength:
320                     return ArrayLength(operand);
321                 case ExpressionType.Convert:
322                     return Convert(operand, type, method);
323                 case ExpressionType.ConvertChecked:
324                     return ConvertChecked(operand, type, method);
325                 case ExpressionType.Throw:
326                     return Throw(operand, type);
327                 case ExpressionType.TypeAs:
328                     return TypeAs(operand, type);
329                 case ExpressionType.Quote:
330                     return Quote(operand);
331                 case ExpressionType.UnaryPlus:
332                     return UnaryPlus(operand, method);
333                 case ExpressionType.Unbox:
334                     return Unbox(operand, type);
335                 case ExpressionType.Increment:
336                     return Increment(operand, method);
337                 case ExpressionType.Decrement:
338                     return Decrement(operand, method);
339                 case ExpressionType.PreIncrementAssign:
340                     return PreIncrementAssign(operand, method);
341                 case ExpressionType.PostIncrementAssign:
342                     return PostIncrementAssign(operand, method);
343                 case ExpressionType.PreDecrementAssign:
344                     return PreDecrementAssign(operand, method);
345                 case ExpressionType.PostDecrementAssign:
346                     return PostDecrementAssign(operand, method);
347                 default:
348                     throw Error.UnhandledUnary(unaryType);
349             }
350         }
351
352         private static UnaryExpression GetUserDefinedUnaryOperatorOrThrow(ExpressionType unaryType, string name, Expression operand) {
353             UnaryExpression u = GetUserDefinedUnaryOperator(unaryType, name, operand);
354             if (u != null) {
355                 ValidateParamswithOperandsOrThrow(u.Method.GetParametersCached()[0].ParameterType, operand.Type, unaryType, name);
356                 return u;
357             }
358             throw Error.UnaryOperatorNotDefined(unaryType, operand.Type);
359         }
360
361         private static UnaryExpression GetUserDefinedUnaryOperator(ExpressionType unaryType, string name, Expression operand) {
362             Type operandType = operand.Type;
363             Type[] types = new Type[] { operandType };
364             Type nnOperandType = TypeUtils.GetNonNullableType(operandType);
365             BindingFlags flags = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
366             MethodInfo method = nnOperandType.GetMethodValidated(name, flags, null, types, null);
367             if (method != null) {
368                 return new UnaryExpression(unaryType, operand, method.ReturnType, method);
369             }
370             // try lifted call
371             if (TypeUtils.IsNullableType(operandType)) {
372                 types[0] = nnOperandType;
373                 method = nnOperandType.GetMethodValidated(name, flags, null, types, null);
374                 if (method != null && method.ReturnType.IsValueType && !TypeUtils.IsNullableType(method.ReturnType)) {
375                     return new UnaryExpression(unaryType, operand, TypeUtils.GetNullableType(method.ReturnType), method);
376                 }
377             }
378             return null;
379         }
380
381         private static UnaryExpression GetMethodBasedUnaryOperator(ExpressionType unaryType, Expression operand, MethodInfo method) {
382             System.Diagnostics.Debug.Assert(method != null);
383             ValidateOperator(method);
384             ParameterInfo[] pms = method.GetParametersCached();
385             if (pms.Length != 1)
386                 throw Error.IncorrectNumberOfMethodCallArguments(method);
387             if (ParameterIsAssignable(pms[0], operand.Type)) {
388                 ValidateParamswithOperandsOrThrow(pms[0].ParameterType, operand.Type, unaryType, method.Name);
389                 return new UnaryExpression(unaryType, operand, method.ReturnType, method);
390             }
391             // check for lifted call
392             if (TypeUtils.IsNullableType(operand.Type) &&
393                 ParameterIsAssignable(pms[0], TypeUtils.GetNonNullableType(operand.Type)) &&
394                 method.ReturnType.IsValueType && !TypeUtils.IsNullableType(method.ReturnType)) {
395                 return new UnaryExpression(unaryType, operand, TypeUtils.GetNullableType(method.ReturnType), method);
396             }
397
398             throw Error.OperandTypesDoNotMatchParameters(unaryType, method.Name);
399         }
400
401         private static UnaryExpression GetUserDefinedCoercionOrThrow(ExpressionType coercionType, Expression expression, Type convertToType) {
402             UnaryExpression u = GetUserDefinedCoercion(coercionType, expression, convertToType);
403             if (u != null) {
404                 return u;
405             }
406             throw Error.CoercionOperatorNotDefined(expression.Type, convertToType);
407         }
408
409         private static UnaryExpression GetUserDefinedCoercion(ExpressionType coercionType, Expression expression, Type convertToType) {
410             MethodInfo method = TypeUtils.GetUserDefinedCoercionMethod(expression.Type, convertToType, false);
411             if (method != null) {
412                 return new UnaryExpression(coercionType, expression, convertToType, method);
413             } else {
414                 return null;
415             }
416         }
417
418         private static UnaryExpression GetMethodBasedCoercionOperator(ExpressionType unaryType, Expression operand, Type convertToType, MethodInfo method) {
419             System.Diagnostics.Debug.Assert(method != null);
420             ValidateOperator(method);
421             ParameterInfo[] pms = method.GetParametersCached();
422             if (pms.Length != 1) {
423                 throw Error.IncorrectNumberOfMethodCallArguments(method);
424             }
425             if (ParameterIsAssignable(pms[0], operand.Type) && TypeUtils.AreEquivalent(method.ReturnType, convertToType)) {
426                 return new UnaryExpression(unaryType, operand, method.ReturnType, method);
427             }
428             // check for lifted call
429             if ((TypeUtils.IsNullableType(operand.Type) || TypeUtils.IsNullableType(convertToType)) &&
430                 ParameterIsAssignable(pms[0], TypeUtils.GetNonNullableType(operand.Type)) &&
431                 TypeUtils.AreEquivalent(method.ReturnType, TypeUtils.GetNonNullableType(convertToType))) {
432                 return new UnaryExpression(unaryType, operand, convertToType, method);
433             }
434             throw Error.OperandTypesDoNotMatchParameters(unaryType, method.Name);
435         }
436
437         /// <summary>
438         /// Creates a <see cref="UnaryExpression"></see> that represents an arithmetic negation operation.
439         /// </summary>
440         /// <param name="expression">An <see cref="Expression"></see> to set the <see cref="P:UnaryExpression.Operand"></see> property equal to.</param>
441         /// <returns>A <see cref="UnaryExpression"></see> that has the <see cref="P:Expression.NodeType"></see> property equal to <see cref="P:ExpressionType.Negate"></see> and the <see cref="P:UnaryExpression.Operand"></see> properties set to the specified value.</returns>
442         /// <exception cref="ArgumentNullException">Thrown when <paramref name="expression"/> is null.</exception>
443         /// <exception cref="InvalidOperationException">Thrown when the unary minus operator is not defined for <see cref="P:Expression.Type"></see></exception>
444         public static UnaryExpression Negate(Expression expression) {
445             return Negate(expression, null);
446         }
447
448         /// <summary>
449         /// Creates a <see cref="UnaryExpression"></see> that represents an arithmetic negation operation.
450         /// </summary>
451         /// <param name="expression">An <see cref="Expression"></see> to set the <see cref="P:UnaryExpression.Operand"></see> property equal to.</param>
452         /// <param name="method">A <see cref="MethodInfo"></see> to set the <see cref="P:UnaryExpression.Method"></see> property equal to.</param>
453         /// <returns>A <see cref="UnaryExpression"></see> that has the <see cref="P:Expression.NodeType"></see> property equal to <see cref="P:ExpressionType.Negate"></see> and the <see cref="P:UnaryExpression.Operand"></see> and <see cref="P:UnaryExpression.Method"></see> properties set to the specified value.</returns>
454         /// <exception cref="ArgumentNullException">Thrown when <paramref name="expression"/> is null.</exception>
455         /// <exception cref="ArgumentException">Thrown when <paramref name="method"/> is not null and the method it represents returns void, is not static (Shared in Visual Basic), or does not take exactly one argument.</exception>
456         /// <exception cref="InvalidOperationException">Thown when <paramref name="method"/> is null and the unary minus operator is not defined for expression.Type or expression.Type (or its corresponding non-nullable type if it is a nullable value type) is not assignable to the argument type of the method represented by method.</exception>
457         public static UnaryExpression Negate(Expression expression, MethodInfo method) {
458             RequiresCanRead(expression, "expression");
459             if (method == null) {
460                 if (TypeUtils.IsArithmetic(expression.Type) && !TypeUtils.IsUnsignedInt(expression.Type)) {
461                     return new UnaryExpression(ExpressionType.Negate, expression, expression.Type, null);
462                 }
463                 return GetUserDefinedUnaryOperatorOrThrow(ExpressionType.Negate, "op_UnaryNegation", expression);
464             }
465             return GetMethodBasedUnaryOperator(ExpressionType.Negate, expression, method);
466         }
467
468         /// <summary>
469         /// Creates a <see cref="UnaryExpression"></see> that represents a unary plus operation.
470         /// </summary>
471         /// <param name="expression">An <see cref="Expression"></see> to set the <see cref="UnaryExpression.Operand"></see> property equal to.</param>
472         /// <returns>A <see cref="UnaryExpression"></see> that has the <see cref="Expression.NodeType"></see> property equal to <see cref="ExpressionType.UnaryPlus"></see> and the <see cref="UnaryExpression.Operand"></see> property set to the specified value.</returns>
473         /// <exception cref="ArgumentNullException">Thrown when <paramref name="expression"/> is null.</exception>
474         /// <exception cref="InvalidOperationException">Thown when the unary minus operator is not defined for expression.Type.</exception>
475         public static UnaryExpression UnaryPlus(Expression expression) {
476             return UnaryPlus(expression, null);
477         }
478
479         /// <summary>
480         /// Creates a <see cref="UnaryExpression"></see> that represents a unary plus operation.
481         /// </summary>
482         /// <param name="expression">An <see cref="Expression"></see> to set the <see cref="UnaryExpression.Operand"></see> property equal to.</param>
483         /// <param name="method">A <see cref="MethodInfo"></see> to set the <see cref="UnaryExpression.Method"></see> property equal to.</param>
484         /// <returns>A <see cref="UnaryExpression"></see> that has the <see cref="Expression.NodeType"></see> property equal to <see cref="ExpressionType.UnaryPlus"></see> and the <see cref="UnaryExpression.Operand"></see> and <see cref="UnaryExpression.Method"></see>property set to the specified value.</returns>
485         /// <exception cref="ArgumentNullException">Thrown when <paramref name="expression"/> is null.</exception>
486         /// <exception cref="ArgumentException">Thrown when <paramref name="method"/> is not null and the method it represents returns void, is not static (Shared in Visual Basic), or does not take exactly one argument.</exception>
487         /// <exception cref="InvalidOperationException">Thown when <paramref name="method"/> is null and the unary minus operator is not defined for expression.Type or expression.Type (or its corresponding non-nullable type if it is a nullable value type) is not assignable to the argument type of the method represented by method.</exception>
488         public static UnaryExpression UnaryPlus(Expression expression, MethodInfo method) {
489             RequiresCanRead(expression, "expression");
490             if (method == null) {
491                 if (TypeUtils.IsArithmetic(expression.Type)) {
492                     return new UnaryExpression(ExpressionType.UnaryPlus, expression, expression.Type, null);
493                 }
494                 return GetUserDefinedUnaryOperatorOrThrow(ExpressionType.UnaryPlus, "op_UnaryPlus", expression);
495             }
496             return GetMethodBasedUnaryOperator(ExpressionType.UnaryPlus, expression, method);
497         }
498
499         /// <summary>Creates a <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that represents an arithmetic negation operation that has overflow checking.</summary>
500         /// <returns>A <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that has the <see cref="P:Microsoft.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:Microsoft.Linq.Expressions.ExpressionType.NegateChecked" /> and the <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Operand" /> property set to the specified value.</returns>
501         /// <param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression" /> to set the <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Operand" /> property equal to.</param>
502         /// <exception cref="T:System.ArgumentNullException">
503         ///   Thrown when <paramref name="expression" /> is null.</exception>
504         /// <exception cref="T:System.InvalidOperationException">Thrown when the unary minus operator is not defined for <paramref name="expression" />.Type.</exception> 
505         public static UnaryExpression NegateChecked(Expression expression) {
506             return NegateChecked(expression, null);
507         }
508
509         ///<summary>Creates a <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that represents an arithmetic negation operation that has overflow checking. The implementing method can be specified.</summary>
510         ///<returns>A <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that has the <see cref="P:Microsoft.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:Microsoft.Linq.Expressions.ExpressionType.NegateChecked" /> and the <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Operand" /> and <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Method" /> properties set to the specified values.</returns>
511         ///<param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression" /> to set the <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Operand" /> property equal to.</param>
512         ///<param name="method">A <see cref="T:System.Reflection.MethodInfo" /> to set the <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Method" /> property equal to.</param>
513         ///<exception cref="T:System.ArgumentNullException">
514         ///<paramref name="expression" /> is null.</exception>
515         ///<exception cref="T:System.ArgumentException">
516         ///<paramref name="method" /> is not null and the method it represents returns void, is not static (Shared in Visual Basic), or does not take exactly one argument.</exception>
517         ///<exception cref="T:System.InvalidOperationException">
518         ///<paramref name="method" /> is null and the unary minus operator is not defined for <paramref name="expression" />.Type.-or-<paramref name="expression" />.Type (or its corresponding non-nullable type if it is a nullable value type) is not assignable to the argument type of the method represented by <paramref name="method" />.</exception>
519         public static UnaryExpression NegateChecked(Expression expression, MethodInfo method) {
520             RequiresCanRead(expression, "expression");
521             if (method == null) {
522                 if (TypeUtils.IsArithmetic(expression.Type) && !TypeUtils.IsUnsignedInt(expression.Type)) {
523                     return new UnaryExpression(ExpressionType.NegateChecked, expression, expression.Type, null);
524                 }
525                 return GetUserDefinedUnaryOperatorOrThrow(ExpressionType.NegateChecked, "op_UnaryNegation", expression);
526             }
527             return GetMethodBasedUnaryOperator(ExpressionType.NegateChecked, expression, method);
528         }
529
530         ///<summary>Creates a <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that represents a bitwise complement operation.</summary>
531         ///<returns>A <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that has the <see cref="P:Microsoft.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:Microsoft.Linq.Expressions.ExpressionType.Not" /> and the <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Operand" /> property set to the specified value.</returns>
532         ///<param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression" /> to set the <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Operand" /> property equal to.</param>
533         ///<exception cref="T:System.ArgumentNullException">
534         ///<paramref name="expression" /> is null.</exception>
535         ///<exception cref="T:System.InvalidOperationException">The unary not operator is not defined for <paramref name="expression" />.Type.</exception>
536         public static UnaryExpression Not(Expression expression) {
537             return Not(expression, null);
538         }
539
540         ///<summary>Creates a <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that represents a bitwise complement operation. The implementing method can be specified.</summary>
541         ///<returns>A <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that has the <see cref="P:Microsoft.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:Microsoft.Linq.Expressions.ExpressionType.Not" /> and the <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Operand" /> and <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Method" /> properties set to the specified values.</returns>
542         ///<param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression" /> to set the <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Operand" /> property equal to.</param>
543         ///<param name="method">A <see cref="T:System.Reflection.MethodInfo" /> to set the <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Method" /> property equal to.</param>
544         ///<exception cref="T:System.ArgumentNullException">
545         ///<paramref name="expression" /> is null.</exception>
546         ///<exception cref="T:System.ArgumentException">
547         ///<paramref name="method" /> is not null and the method it represents returns void, is not static (Shared in Visual Basic), or does not take exactly one argument.</exception>
548         ///<exception cref="T:System.InvalidOperationException">
549         ///<paramref name="method" /> is null and the unary not operator is not defined for <paramref name="expression" />.Type.-or-<paramref name="expression" />.Type (or its corresponding non-nullable type if it is a nullable value type) is not assignable to the argument type of the method represented by <paramref name="method" />.</exception>
550         public static UnaryExpression Not(Expression expression, MethodInfo method) {
551             RequiresCanRead(expression, "expression");
552             if (method == null) {
553                 if (TypeUtils.IsIntegerOrBool(expression.Type)) {
554                     return new UnaryExpression(ExpressionType.Not, expression, expression.Type, null);
555                 }
556                 UnaryExpression u = GetUserDefinedUnaryOperator(ExpressionType.Not, "op_LogicalNot", expression);
557                 if (u != null) {
558                     return u;
559                 }
560                 return GetUserDefinedUnaryOperatorOrThrow(ExpressionType.Not, "op_OnesComplement", expression);
561             }
562             return GetMethodBasedUnaryOperator(ExpressionType.Not, expression, method);
563         }
564
565         /// <summary>
566         /// Returns whether the expression evaluates to false.
567         /// </summary>
568         /// <param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression" /> to evaluate.</param>
569         /// <returns>An instance of <see cref="UnaryExpression"/>.</returns>
570         public static UnaryExpression IsFalse(Expression expression) {
571             return IsFalse(expression, null);
572         }
573
574         /// <summary>
575         /// Returns whether the expression evaluates to false.
576         /// </summary>
577         ///<param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression" /> to evaluate.</param>
578         ///<param name="method">A <see cref="T:System.Reflection.MethodInfo" /> that represents the implementing method.</param>
579         /// <returns>An instance of <see cref="UnaryExpression"/>.</returns>
580         public static UnaryExpression IsFalse(Expression expression, MethodInfo method) {
581             RequiresCanRead(expression, "expression");
582             if (method == null) {
583                 if (TypeUtils.IsBool(expression.Type)) {
584                     return new UnaryExpression(ExpressionType.IsFalse, expression, expression.Type, null);
585                 }
586                 return GetUserDefinedUnaryOperatorOrThrow(ExpressionType.IsFalse, "op_False", expression);
587             }
588             return GetMethodBasedUnaryOperator(ExpressionType.IsFalse, expression, method);
589         }
590
591         /// <summary>
592         /// Returns whether the expression evaluates to true.
593         /// </summary>
594         /// <param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression" /> to evaluate.</param>
595         /// <returns>An instance of <see cref="UnaryExpression"/>.</returns>
596         public static UnaryExpression IsTrue(Expression expression) {
597             return IsTrue(expression, null);
598         }
599
600         /// <summary>
601         /// Returns whether the expression evaluates to true.
602         /// </summary>
603         ///<param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression" /> to evaluate.</param>
604         ///<param name="method">A <see cref="T:System.Reflection.MethodInfo" /> that represents the implementing method.</param>
605         /// <returns>An instance of <see cref="UnaryExpression"/>.</returns>
606         public static UnaryExpression IsTrue(Expression expression, MethodInfo method) {
607             RequiresCanRead(expression, "expression");
608             if (method == null) {
609                 if (TypeUtils.IsBool(expression.Type)) {
610                     return new UnaryExpression(ExpressionType.IsTrue, expression, expression.Type, null);
611                 }
612                 return GetUserDefinedUnaryOperatorOrThrow(ExpressionType.IsTrue, "op_True", expression);
613             }
614             return GetMethodBasedUnaryOperator(ExpressionType.IsTrue, expression, method);
615         }
616
617         /// <summary>
618         /// Returns the expression representing the ones complement.
619         /// </summary>
620         ///<param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression" />.</param>
621         /// <returns>An instance of <see cref="UnaryExpression"/>.</returns>
622         public static UnaryExpression OnesComplement(Expression expression) {
623             return OnesComplement(expression, null);
624         }
625
626         /// <summary>
627         /// Returns the expression representing the ones complement.
628         /// </summary>
629         /// <param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression" />.</param>
630         /// <param name="method">A <see cref="T:System.Reflection.MethodInfo" /> that represents the implementing method.</param>
631         /// <returns>An instance of <see cref="UnaryExpression"/>.</returns>
632         public static UnaryExpression OnesComplement(Expression expression, MethodInfo method) {
633             RequiresCanRead(expression, "expression");
634             if (method == null) {
635                 if (TypeUtils.IsInteger(expression.Type)) {
636                     return new UnaryExpression(ExpressionType.OnesComplement, expression, expression.Type, null);
637                 }
638                 return GetUserDefinedUnaryOperatorOrThrow(ExpressionType.OnesComplement, "op_OnesComplement", expression);
639             }
640             return GetMethodBasedUnaryOperator(ExpressionType.OnesComplement, expression, method);
641         }
642
643         ///<summary>Creates a <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that represents an explicit reference or boxing conversion where null is supplied if the conversion fails.</summary>
644         ///<returns>A <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that has the <see cref="P:Microsoft.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:Microsoft.Linq.Expressions.ExpressionType.TypeAs" /> and the <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Operand" /> and <see cref="P:Microsoft.Linq.Expressions.Expression.Type" /> properties set to the specified values.</returns>
645         ///<param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression" /> to set the <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Operand" /> property equal to.</param>
646         ///<param name="type">A <see cref="T:System.Type" /> to set the <see cref="P:Microsoft.Linq.Expressions.Expression.Type" /> property equal to.</param>
647         ///<exception cref="T:System.ArgumentNullException">
648         ///<paramref name="expression" /> or <paramref name="type" /> is null.</exception>
649         public static UnaryExpression TypeAs(Expression expression, Type type) {
650             RequiresCanRead(expression, "expression");
651             ContractUtils.RequiresNotNull(type, "type");
652             TypeUtils.ValidateType(type);
653
654             if (type.IsValueType && !TypeUtils.IsNullableType(type)) {
655                 throw Error.IncorrectTypeForTypeAs(type);
656             }
657             return new UnaryExpression(ExpressionType.TypeAs, expression, type, null);
658         }
659
660         /// <summary>
661         /// <summary>Creates a <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that represents an explicit unboxing.</summary>
662         /// </summary>     
663         /// <param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression" /> to unbox.</param>
664         /// <param name="type">The new <see cref="T:System.Type" /> of the expression.</param>
665         /// <returns>An instance of <see cref="UnaryExpression"/>.</returns>
666         public static UnaryExpression Unbox(Expression expression, Type type) {
667             RequiresCanRead(expression, "expression");
668             ContractUtils.RequiresNotNull(type, "type");
669             ContractUtils.Requires(
670                 expression.Type.IsInterface || expression.Type == typeof(object),
671                 "expression", Strings.InvalidUnboxType
672             );
673             ContractUtils.Requires(type.IsValueType, "type", Strings.InvalidUnboxType);
674             TypeUtils.ValidateType(type);
675             return new UnaryExpression(ExpressionType.Unbox, expression, type, null);
676         }
677
678         ///<summary>Creates a <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that represents a conversion operation.</summary>
679         ///<returns>A <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that has the <see cref="P:Microsoft.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:Microsoft.Linq.Expressions.ExpressionType.Convert" /> and the <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Operand" /> and <see cref="P:Microsoft.Linq.Expressions.Expression.Type" /> properties set to the specified values.</returns>
680         ///<param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression" /> to set the <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Operand" /> property equal to.</param>
681         ///<param name="type">A <see cref="T:System.Type" /> to set the <see cref="P:Microsoft.Linq.Expressions.Expression.Type" /> property equal to.</param>
682         ///<exception cref="T:System.ArgumentNullException">
683         ///<paramref name="expression" /> or <paramref name="type" /> is null.</exception>
684         ///<exception cref="T:System.InvalidOperationException">No conversion operator is defined between <paramref name="expression" />.Type and <paramref name="type" />.</exception>
685         public static UnaryExpression Convert(Expression expression, Type type) {
686             return Convert(expression, type, null);
687         }
688
689         ///<summary>Creates a <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that represents a conversion operation for which the implementing method is specified.</summary>
690         ///<returns>A <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that has the <see cref="P:Microsoft.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:Microsoft.Linq.Expressions.ExpressionType.Convert" /> and the <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Operand" />, <see cref="P:Microsoft.Linq.Expressions.Expression.Type" />, and <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Method" /> properties set to the specified values.</returns>
691         ///<param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression" /> to set the <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Operand" /> property equal to.</param>
692         ///<param name="type">A <see cref="T:System.Type" /> to set the <see cref="P:Microsoft.Linq.Expressions.Expression.Type" /> property equal to.</param>
693         ///<param name="method">A <see cref="T:System.Reflection.MethodInfo" /> to set the <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Method" /> property equal to.</param>
694         ///<exception cref="T:System.ArgumentNullException">
695         ///<paramref name="expression" /> or <paramref name="type" /> is null.</exception>
696         ///<exception cref="T:System.ArgumentException">
697         ///<paramref name="method" /> is not null and the method it represents returns void, is not static (Shared in Visual Basic), or does not take exactly one argument.</exception>
698         ///<exception cref="T:System.Reflection.AmbiguousMatchException">More than one method that matches the <paramref name="method" /> description was found.</exception>
699         ///<exception cref="T:System.InvalidOperationException">No conversion operator is defined between <paramref name="expression" />.Type and <paramref name="type" />.-or-<paramref name="expression" />.Type is not assignable to the argument type of the method represented by <paramref name="method" />.-or-The return type of the method represented by <paramref name="method" /> is not assignable to <paramref name="type" />.-or-<paramref name="expression" />.Type or <paramref name="type" /> is a nullable value type and the corresponding non-nullable value type does not equal the argument type or the return type, respectively, of the method represented by <paramref name="method" />.</exception>
700         public static UnaryExpression Convert(Expression expression, Type type, MethodInfo method) {
701             RequiresCanRead(expression, "expression");
702             ContractUtils.RequiresNotNull(type, "type");
703             TypeUtils.ValidateType(type);
704
705             if (method == null) {
706                 if (TypeUtils.HasIdentityPrimitiveOrNullableConversion(expression.Type, type) ||
707                     TypeUtils.HasReferenceConversion(expression.Type, type)) {
708                     return new UnaryExpression(ExpressionType.Convert, expression, type, null);
709                 }
710                 return GetUserDefinedCoercionOrThrow(ExpressionType.Convert, expression, type);
711             }
712             return GetMethodBasedCoercionOperator(ExpressionType.Convert, expression, type, method);
713         }
714
715         ///<summary>Creates a <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that represents a conversion operation that throws an exception if the target type is overflowed.</summary>
716         ///<returns>A <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that has the <see cref="P:Microsoft.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:Microsoft.Linq.Expressions.ExpressionType.ConvertChecked" /> and the <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Operand" /> and <see cref="P:Microsoft.Linq.Expressions.Expression.Type" /> properties set to the specified values.</returns>
717         ///<param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression" /> to set the <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Operand" /> property equal to.</param>
718         ///<param name="type">A <see cref="T:System.Type" /> to set the <see cref="P:Microsoft.Linq.Expressions.Expression.Type" /> property equal to.</param>
719         ///<exception cref="T:System.ArgumentNullException">
720         ///<paramref name="expression" /> or <paramref name="type" /> is null.</exception>
721         ///<exception cref="T:System.InvalidOperationException">No conversion operator is defined between <paramref name="expression" />.Type and <paramref name="type" />.</exception>
722         public static UnaryExpression ConvertChecked(Expression expression, Type type) {
723             return ConvertChecked(expression, type, null);
724         }
725
726         ///<summary>Creates a <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that represents a conversion operation that throws an exception if the target type is overflowed and for which the implementing method is specified.</summary>
727         ///<returns>A <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that has the <see cref="P:Microsoft.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:Microsoft.Linq.Expressions.ExpressionType.ConvertChecked" /> and the <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Operand" />, <see cref="P:Microsoft.Linq.Expressions.Expression.Type" />, and <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Method" /> properties set to the specified values.</returns>
728         ///<param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression" /> to set the <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Operand" /> property equal to.</param>
729         ///<param name="type">A <see cref="T:System.Type" /> to set the <see cref="P:Microsoft.Linq.Expressions.Expression.Type" /> property equal to.</param>
730         ///<param name="method">A <see cref="T:System.Reflection.MethodInfo" /> to set the <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Method" /> property equal to.</param>
731         ///<exception cref="T:System.ArgumentNullException">
732         ///<paramref name="expression" /> or <paramref name="type" /> is null.</exception>
733         ///<exception cref="T:System.ArgumentException">
734         ///<paramref name="method" /> is not null and the method it represents returns void, is not static (Shared in Visual Basic), or does not take exactly one argument.</exception>
735         ///<exception cref="T:System.Reflection.AmbiguousMatchException">More than one method that matches the <paramref name="method" /> description was found.</exception>
736         ///<exception cref="T:System.InvalidOperationException">No conversion operator is defined between <paramref name="expression" />.Type and <paramref name="type" />.-or-<paramref name="expression" />.Type is not assignable to the argument type of the method represented by <paramref name="method" />.-or-The return type of the method represented by <paramref name="method" /> is not assignable to <paramref name="type" />.-or-<paramref name="expression" />.Type or <paramref name="type" /> is a nullable value type and the corresponding non-nullable value type does not equal the argument type or the return type, respectively, of the method represented by <paramref name="method" />.</exception>
737         public static UnaryExpression ConvertChecked(Expression expression, Type type, MethodInfo method) {
738             RequiresCanRead(expression, "expression");
739             ContractUtils.RequiresNotNull(type, "type");
740             TypeUtils.ValidateType(type);
741
742             if (method == null) {
743                 if (TypeUtils.HasIdentityPrimitiveOrNullableConversion(expression.Type, type)) {
744                     return new UnaryExpression(ExpressionType.ConvertChecked, expression, type, null);
745                 }
746                 if (TypeUtils.HasReferenceConversion(expression.Type, type)) {
747                     return new UnaryExpression(ExpressionType.Convert, expression, type, null);
748                 }
749                 return GetUserDefinedCoercionOrThrow(ExpressionType.ConvertChecked, expression, type);
750             }
751             return GetMethodBasedCoercionOperator(ExpressionType.ConvertChecked, expression, type, method);
752         }
753
754         ///<summary>Creates a <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that represents getting the length of a one-dimensional array.</summary>
755         ///<returns>A <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that has the <see cref="P:Microsoft.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:Microsoft.Linq.Expressions.ExpressionType.ArrayLength" /> and the <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Operand" /> property equal to <paramref name="array" />.</returns>
756         ///<param name="array">An <see cref="T:Microsoft.Linq.Expressions.Expression" /> to set the <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Operand" /> property equal to.</param>
757         ///<exception cref="T:System.ArgumentNullException">
758         ///<paramref name="array" /> is null.</exception>
759         ///<exception cref="T:System.ArgumentException">
760         ///<paramref name="array" />.Type does not represent an array type.</exception>
761         public static UnaryExpression ArrayLength(Expression array) {
762             ContractUtils.RequiresNotNull(array, "array");
763             if (!array.Type.IsArray || !typeof(Array).IsAssignableFrom(array.Type)) {
764                 throw Error.ArgumentMustBeArray();
765             }
766             if (array.Type.GetArrayRank() != 1) {
767                 throw Error.ArgumentMustBeSingleDimensionalArrayType();
768             }
769             return new UnaryExpression(ExpressionType.ArrayLength, array, typeof(int), null);
770         }
771
772         ///<summary>Creates a <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that represents an expression that has a constant value of type <see cref="T:Microsoft.Linq.Expressions.Expression" />.</summary>
773         ///<returns>A <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that has the <see cref="P:Microsoft.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:Microsoft.Linq.Expressions.ExpressionType.Quote" /> and the <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Operand" /> property set to the specified value.</returns>
774         ///<param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression" /> to set the <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Operand" /> property equal to.</param>
775         ///<exception cref="T:System.ArgumentNullException">
776         ///<paramref name="expression" /> is null.</exception>
777         public static UnaryExpression Quote(Expression expression) {
778             RequiresCanRead(expression, "expression");
779             ContractUtils.Requires(expression is LambdaExpression, Strings.QuotedExpressionMustBeLambda);
780             return new UnaryExpression(ExpressionType.Quote, expression, expression.GetType(), null);
781         }
782
783         /// <summary>
784         /// Creates a <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that represents a rethrowing of an exception.
785         /// </summary>
786         /// <returns>A <see cref="T:Microsoft.Linq.Expressions.UnaryExpression"/> that represents a rethrowing of an exception.</returns>
787         public static UnaryExpression Rethrow() {
788             return Throw(null);
789         }
790
791         /// <summary>
792         /// Creates a <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that represents a rethrowing of an exception with a given type.
793         /// </summary>
794         ///<param name="type">The new <see cref="T:System.Type" /> of the expression.</param>
795         /// <returns>A <see cref="T:Microsoft.Linq.Expressions.UnaryExpression"/> that represents a rethrowing of an exception.</returns>
796         public static UnaryExpression Rethrow(Type type) {
797             return Throw(null, type);
798         }
799
800         /// <summary>
801         /// Creates a <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that represents a throwing of an exception.
802         /// </summary>
803         /// <param name="value">An <see cref="T:Microsoft.Linq.Expressions.Expression" />.</param>
804         /// <returns>A <see cref="T:Microsoft.Linq.Expressions.UnaryExpression"/> that represents the exception.</returns>
805         public static UnaryExpression Throw(Expression value) {
806             return Throw(value, typeof(void));
807         }
808
809         /// <summary>
810         /// Creates a <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that represents a throwing of a value with a given type.
811         /// </summary>
812         /// <param name="value">An <see cref="T:Microsoft.Linq.Expressions.Expression" />.</param>
813         /// <param name="type">The new <see cref="T:System.Type" /> of the expression.</param>
814         /// <returns>A <see cref="T:Microsoft.Linq.Expressions.UnaryExpression"/> that represents the exception.</returns>
815         public static UnaryExpression Throw(Expression value, Type type) {
816             ContractUtils.RequiresNotNull(type, "type");
817             TypeUtils.ValidateType(type);
818
819             if (value != null) {
820                 RequiresCanRead(value, "value");
821                 ContractUtils.Requires(!value.Type.IsValueType, "value", Strings.ArgumentMustNotHaveValueType);
822             }
823             return new UnaryExpression(ExpressionType.Throw, value, type, null);
824         }
825
826         /// <summary>
827         /// Creates a <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that represents the incrementing of the expression by 1.
828         /// </summary>
829         /// <param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression"></see> to increment.</param>
830         /// <returns>A <see cref="T:Microsoft.Linq.Expressions.UnaryExpression"/> that represents the incremented expression.</returns>
831         public static UnaryExpression Increment(Expression expression) {
832             return Increment(expression, null);
833         }
834
835         /// <summary>
836         /// Creates a <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that represents the incrementing of the expression by 1.
837         /// </summary>
838         /// <param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression"></see> to increment.</param>
839         ///<param name="method">A <see cref="T:System.Reflection.MethodInfo" /> that represents the implementing method.</param>
840         /// <returns>A <see cref="T:Microsoft.Linq.Expressions.UnaryExpression"/> that represents the incremented expression.</returns>
841         public static UnaryExpression Increment(Expression expression, MethodInfo method) {
842             RequiresCanRead(expression, "expression");
843             if (method == null) {
844                 if (TypeUtils.IsArithmetic(expression.Type)) {
845                     return new UnaryExpression(ExpressionType.Increment, expression, expression.Type, null);
846                 }
847                 return GetUserDefinedUnaryOperatorOrThrow(ExpressionType.Increment, "op_Increment", expression);
848             }
849             return GetMethodBasedUnaryOperator(ExpressionType.Increment, expression, method);
850         }
851
852         /// <summary>
853         /// Creates a <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that represents the decrementing of the expression by 1.
854         /// </summary>
855         /// <param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression"></see> to decrement.</param>
856         /// <returns>A <see cref="T:Microsoft.Linq.Expressions.UnaryExpression"/> that represents the decremented expression.</returns>
857         public static UnaryExpression Decrement(Expression expression) {
858             return Decrement(expression, null);
859         }
860
861         /// <summary>
862         /// Creates a <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that represents the decrementing of the expression by 1.
863         /// </summary>
864         /// <param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression"></see> to decrement.</param>
865         ///<param name="method">A <see cref="T:System.Reflection.MethodInfo" /> that represents the implementing method.</param>
866         /// <returns>A <see cref="T:Microsoft.Linq.Expressions.UnaryExpression"/> that represents the decremented expression.</returns>
867         public static UnaryExpression Decrement(Expression expression, MethodInfo method) {
868             RequiresCanRead(expression, "expression");
869             if (method == null) {
870                 if (TypeUtils.IsArithmetic(expression.Type)) {
871                     return new UnaryExpression(ExpressionType.Decrement, expression, expression.Type, null);
872                 }
873                 return GetUserDefinedUnaryOperatorOrThrow(ExpressionType.Decrement, "op_Decrement", expression);
874             }
875             return GetMethodBasedUnaryOperator(ExpressionType.Decrement, expression, method);
876         }
877
878         /// <summary>
879         /// Creates a <see cref="UnaryExpression"/> that increments the expression by 1
880         /// and assigns the result back to the expression.
881         /// </summary>
882         /// <param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression"></see> to apply the operations on.</param>
883         /// <returns>A <see cref="T:Microsoft.Linq.Expressions.UnaryExpression"/> that represents the resultant expression.</returns>
884         public static UnaryExpression PreIncrementAssign(Expression expression) {
885             return MakeOpAssignUnary(ExpressionType.PreIncrementAssign, expression, null);
886
887         }
888
889         /// <summary>
890         /// Creates a <see cref="UnaryExpression"/> that increments the expression by 1
891         /// and assigns the result back to the expression.
892         /// </summary>
893         /// <param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression"></see> to apply the operations on.</param>
894         /// <param name="method">A <see cref="T:System.Reflection.MethodInfo" /> that represents the implementing method.</param>
895         /// <returns>A <see cref="T:Microsoft.Linq.Expressions.UnaryExpression"/> that represents the resultant expression.</returns>
896         public static UnaryExpression PreIncrementAssign(Expression expression, MethodInfo method) {
897             return MakeOpAssignUnary(ExpressionType.PreIncrementAssign, expression, method);
898         }
899
900         /// <summary>
901         /// Creates a <see cref="UnaryExpression"/> that decrements the expression by 1
902         /// and assigns the result back to the expression.
903         /// </summary>
904         /// <param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression"></see> to apply the operations on.</param>
905         /// <returns>A <see cref="T:Microsoft.Linq.Expressions.UnaryExpression"/> that represents the resultant expression.</returns>
906         public static UnaryExpression PreDecrementAssign(Expression expression) {
907             return MakeOpAssignUnary(ExpressionType.PreDecrementAssign, expression, null);
908         }
909
910         /// <summary>
911         /// Creates a <see cref="UnaryExpression"/> that decrements the expression by 1
912         /// and assigns the result back to the expression.
913         /// </summary>
914         /// <param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression"></see> to apply the operations on.</param>
915         /// <param name="method">A <see cref="T:System.Reflection.MethodInfo" /> that represents the implementing method.</param>
916         /// <returns>A <see cref="T:Microsoft.Linq.Expressions.UnaryExpression"/> that represents the resultant expression.</returns>
917         public static UnaryExpression PreDecrementAssign(Expression expression, MethodInfo method) {
918             return MakeOpAssignUnary(ExpressionType.PreDecrementAssign, expression, method);
919         }
920
921         /// <summary>
922         /// Creates a <see cref="UnaryExpression"/> that represents the assignment of the expression 
923         /// followed by a subsequent increment by 1 of the original expression.
924         /// </summary>
925         /// <param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression"></see> to apply the operations on.</param>
926         /// <returns>A <see cref="T:Microsoft.Linq.Expressions.UnaryExpression"/> that represents the resultant expression.</returns>
927         public static UnaryExpression PostIncrementAssign(Expression expression) {
928             return MakeOpAssignUnary(ExpressionType.PostIncrementAssign, expression, null);
929         }
930
931         /// <summary>
932         /// Creates a <see cref="UnaryExpression"/> that represents the assignment of the expression 
933         /// followed by a subsequent increment by 1 of the original expression.
934         /// </summary>
935         /// <param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression"></see> to apply the operations on.</param>
936         /// <param name="method">A <see cref="T:System.Reflection.MethodInfo" /> that represents the implementing method.</param>
937         /// <returns>A <see cref="T:Microsoft.Linq.Expressions.UnaryExpression"/> that represents the resultant expression.</returns>
938         public static UnaryExpression PostIncrementAssign(Expression expression, MethodInfo method) {
939             return MakeOpAssignUnary(ExpressionType.PostIncrementAssign, expression, method);
940         }
941
942         /// <summary>
943         /// Creates a <see cref="UnaryExpression"/> that represents the assignment of the expression 
944         /// followed by a subsequent decrement by 1 of the original expression.
945         /// </summary>
946         /// <param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression"></see> to apply the operations on.</param>
947         /// <returns>A <see cref="T:Microsoft.Linq.Expressions.UnaryExpression"/> that represents the resultant expression.</returns>
948         public static UnaryExpression PostDecrementAssign(Expression expression) {
949             return MakeOpAssignUnary(ExpressionType.PostDecrementAssign, expression, null);
950         }
951
952         /// <summary>
953         /// Creates a <see cref="UnaryExpression"/> that represents the assignment of the expression 
954         /// followed by a subsequent decrement by 1 of the original expression.
955         /// </summary>
956         /// <param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression"></see> to apply the operations on.</param>
957         /// <param name="method">A <see cref="T:System.Reflection.MethodInfo" /> that represents the implementing method.</param>
958         /// <returns>A <see cref="T:Microsoft.Linq.Expressions.UnaryExpression"/> that represents the resultant expression.</returns>
959         public static UnaryExpression PostDecrementAssign(Expression expression, MethodInfo method) {
960             return MakeOpAssignUnary(ExpressionType.PostDecrementAssign, expression, method);
961         }
962
963         private static UnaryExpression MakeOpAssignUnary(ExpressionType kind, Expression expression, MethodInfo method) {
964             RequiresCanRead(expression, "expression");
965             RequiresCanWrite(expression, "expression");
966
967             UnaryExpression result;
968             if (method == null) {
969                 if (TypeUtils.IsArithmetic(expression.Type)) {
970                     return new UnaryExpression(kind, expression, expression.Type, null);
971                 }
972                 string name;
973                 if (kind == ExpressionType.PreIncrementAssign || kind == ExpressionType.PostIncrementAssign) {
974                     name = "op_Increment";
975                 } else {
976                     name = "op_Decrement";
977                 }
978                 result = GetUserDefinedUnaryOperatorOrThrow(kind, name, expression);
979             } else {
980                 result = GetMethodBasedUnaryOperator(kind, expression, method);
981             }
982             // return type must be assignable back to the operand type
983             if (!TypeUtils.AreReferenceAssignable(expression.Type, result.Type)) {
984                 throw Error.UserDefinedOpMustHaveValidReturnType(kind, method.Name);
985             }
986             return result;
987         }
988     }
989 }