UnaryExpression.cs :  » Script » IronRuby » Microsoft » Scripting » Ast » C# / CSharp Open Source

Home
C# / CSharp Open Source
1.2.6.4 mono .net core
2.2.6.4 mono core
3.Aspect Oriented Frameworks
4.Bloggers
5.Build Systems
6.Business Application
7.Charting Reporting Tools
8.Chat Servers
9.Code Coverage Tools
10.Content Management Systems CMS
11.CRM ERP
12.Database
13.Development
14.Email
15.Forum
16.Game
17.GIS
18.GUI
19.IDEs
20.Installers Generators
21.Inversion of Control Dependency Injection
22.Issue Tracking
23.Logging Tools
24.Message
25.Mobile
26.Network Clients
27.Network Servers
28.Office
29.PDF
30.Persistence Frameworks
31.Portals
32.Profilers
33.Project Management
34.RSS RDF
35.Rule Engines
36.Script
37.Search Engines
38.Sound Audio
39.Source Control
40.SQL Clients
41.Template Engines
42.Testing
43.UML
44.Web Frameworks
45.Web Service
46.Web Testing
47.Wiki Engines
48.Windows Presentation Foundation
49.Workflows
50.XML Parsers
C# / C Sharp
C# / C Sharp by API
C# / CSharp Tutorial
C# / CSharp Open Source » Script » IronRuby 
IronRuby » Microsoft » Scripting » Ast » UnaryExpression.cs
/* ****************************************************************************
 *
 * Copyright (c) Microsoft Corporation. 
 *
 * This source code is subject to terms and conditions of the Microsoft Public License. A 
 * copy of the license can be found in the License.html file at the root of this distribution. If 
 * you cannot locate the  Microsoft Public License, please send an email to 
 * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound 
 * by the terms of the Microsoft Public License.
 *
 * You must not remove this notice, or any other, from this software.
 *
 *
 * ***************************************************************************/

using System;
using System.Diagnostics;
using System.Dynamic.Utils;
using System.Reflection;
using System.Runtime.CompilerServices;

#if SILVERLIGHT
using System.Core;
#endif

#if CLR2
namespace Microsoft.Scripting.Ast{
#else
namespace System.Linq.Expressions {
#endif

    /// <summary>
    /// Represents an expression that has a unary operator.
    /// </summary>
#if !SILVERLIGHT
    [DebuggerTypeProxy(typeof(Expression.UnaryExpressionProxy))]
#endif
    public sealed class UnaryExpression : Expression {
        private readonly Expression _operand;
        private readonly MethodInfo _method;
        private readonly ExpressionType _nodeType;
        private readonly Type _type;

        internal UnaryExpression(ExpressionType nodeType, Expression expression, Type type, MethodInfo method) {
            _operand = expression;
            _method = method;
            _nodeType = nodeType;
            _type = type;
        }

        /// <summary>
        /// Gets the static type of the expression that this <see cref="Expression" /> represents. (Inherited from <see cref="Expression"/>.)
        /// </summary>
        /// <returns>The <see cref="Type"/> that represents the static type of the expression.</returns>
        public sealed override Type Type {
            get { return _type; }
        }

        /// <summary>
        /// Returns the node type of this <see cref="Expression" />. (Inherited from <see cref="Expression" />.)
        /// </summary>
        /// <returns>The <see cref="ExpressionType"/> that represents this expression.</returns>
        public sealed override ExpressionType NodeType {
            get { return _nodeType; }
        }

        /// <summary>
        /// Gets the operand of the unary operation.
        /// </summary>
        /// <returns> An <see cref="ExpressionType"/> that represents the operand of the unary operation.</returns>
        public Expression Operand {
            get { return _operand; }
        }

        /// <summary>
        /// Gets the implementing method for the unary operation.
        /// </summary>
        /// <returns>The <see cref="MethodInfo"/> that represents the implementing method.</returns>
        public MethodInfo Method {
            get { return _method; }
        }

        /// <summary>
        /// Gets a value that indicates whether the expression tree node represents a lifted call to an operator.
        /// </summary>
        /// <returns>true if the node represents a lifted call; otherwise, false.</returns>
        public bool IsLifted {
            get {
                if (NodeType == ExpressionType.TypeAs || NodeType == ExpressionType.Quote || NodeType == ExpressionType.Throw) {
                    return false;
                }
                bool operandIsNullable = TypeUtils.IsNullableType(_operand.Type);
                bool resultIsNullable = TypeUtils.IsNullableType(this.Type);
                if (_method != null) {
                    return (operandIsNullable && !TypeUtils.AreEquivalent(_method.GetParametersCached()[0].ParameterType, _operand.Type)) ||
                           (resultIsNullable && !TypeUtils.AreEquivalent(_method.ReturnType, this.Type));
                }
                return operandIsNullable || resultIsNullable;
            }
        }

        /// <summary>
        /// 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.
        /// </summary>
        /// <returns>true if the operator's return type is lifted to a nullable type; otherwise, false.</returns>
        public bool IsLiftedToNull {
            get {
                return IsLifted && TypeUtils.IsNullableType(this.Type);
            }
        }

        /// <summary>
        /// Dispatches to the specific visit method for this node type.
        /// </summary>
        protected internal override Expression Accept(ExpressionVisitor visitor) {
            return visitor.VisitUnary(this);
        }

        /// <summary>
        /// Gets a value that indicates whether the expression tree node can be reduced. 
        /// </summary>        
        public override bool CanReduce {
            get {
                switch (_nodeType) {
                    case ExpressionType.PreIncrementAssign:
                    case ExpressionType.PreDecrementAssign:
                    case ExpressionType.PostIncrementAssign:
                    case ExpressionType.PostDecrementAssign:
                        return true;
                }
                return false;
            }
        }

        /// <summary>
        /// Reduces the expression node to a simpler expression. 
        /// If CanReduce returns true, this should return a valid expression.
        /// This method is allowed to return another node which itself 
        /// must be reduced.
        /// </summary>
        /// <returns>The reduced expression.</returns>
        public override Expression Reduce() {
            if (CanReduce) {
                switch (_operand.NodeType) {
                    case ExpressionType.Index:
                        return ReduceIndex();
                    case ExpressionType.MemberAccess:
                        return ReduceMember();
                    default:
                        return ReduceVariable();
                }
            }
            return this;
        }

        private bool IsPrefix {
            get { return _nodeType == ExpressionType.PreIncrementAssign || _nodeType == ExpressionType.PreDecrementAssign; }
        }

        private UnaryExpression FunctionalOp(Expression operand) {
            ExpressionType functional;
            if (_nodeType == ExpressionType.PreIncrementAssign || _nodeType == ExpressionType.PostIncrementAssign) {
                functional = ExpressionType.Increment;
            } else {
                functional = ExpressionType.Decrement;
            }
            return new UnaryExpression(functional, operand, operand.Type, _method);
        }

        private Expression ReduceVariable() {
            if (IsPrefix) {
                // (op) var
                // ... is reduced into ...
                // var = op(var)
                return Assign(_operand, FunctionalOp(_operand));
            }
            // var (op)
            // ... is reduced into ...
            // temp = var
            // var = op(var)
            // temp
            var temp = Parameter(_operand.Type, null);
            return Block(
                new[] { temp },
                Assign(temp, _operand),
                Assign(_operand, FunctionalOp(temp)),
                temp
            );
        }

        private Expression ReduceMember() {
            var member = (MemberExpression)_operand;
            if (member.Expression == null) {
                //static member, reduce the same as variable
                return ReduceVariable();
            } else {
                var temp1 = Parameter(member.Expression.Type, null);
                var initTemp1 = Assign(temp1, member.Expression);
                member = MakeMemberAccess(temp1, member.Member);

                if (IsPrefix) {
                    // (op) value.member
                    // ... is reduced into ...
                    // temp1 = value
                    // temp1.member = op(temp1.member)
                    return Block(
                        new[] { temp1 },
                        initTemp1,
                        Assign(member, FunctionalOp(member))
                    );
                }

                // value.member (op)
                // ... is reduced into ...
                // temp1 = value
                // temp2 = temp1.member
                // temp1.member = op(temp2)
                // temp2
                var temp2 = Parameter(member.Type, null);
                return Block(
                    new[] { temp1, temp2 },
                    initTemp1,
                    Assign(temp2, member),
                    Assign(member, FunctionalOp(temp2)),
                    temp2
                );
            }
        }

        private Expression ReduceIndex() {
            // left[a0, a1, ... aN] (op)
            //
            // ... is reduced into ...
            //
            // tempObj = left
            // tempArg0 = a0
            // ...
            // tempArgN = aN
            // tempValue = tempObj[tempArg0, ... tempArgN]
            // tempObj[tempArg0, ... tempArgN] = op(tempValue)
            // tempValue

            bool prefix = IsPrefix;
            var index = (IndexExpression)_operand;
            int count = index.Arguments.Count;
            var block = new Expression[count + (prefix ? 2 : 4)];
            var temps = new ParameterExpression[count + (prefix ? 1 : 2)];
            var args = new ParameterExpression[count];

            int i = 0;
            temps[i] = Parameter(index.Object.Type, null);
            block[i] = Assign(temps[i], index.Object);
            i++;
            while (i <= count) {
                var arg = index.Arguments[i - 1];
                args[i - 1] = temps[i] = Parameter(arg.Type, null);
                block[i] = Assign(temps[i], arg);
                i++;
            }
            index = MakeIndex(temps[0], index.Indexer, new TrueReadOnlyCollection<Expression>(args));
            if (!prefix) {
                var lastTemp = temps[i] = Parameter(index.Type, null);
                block[i] = Assign(temps[i], index);
                i++;
                Debug.Assert(i == temps.Length);
                block[i++] = Assign(index, FunctionalOp(lastTemp));
                block[i++] = lastTemp;
            } else {
                Debug.Assert(i == temps.Length);
                block[i++] = Assign(index, FunctionalOp(index));
            }
            Debug.Assert(i == block.Length);
            return Block(new TrueReadOnlyCollection<ParameterExpression>(temps), new TrueReadOnlyCollection<Expression>(block));
        }

        /// <summary>
        /// Creates a new expression that is like this one, but using the
        /// supplied children. If all of the children are the same, it will
        /// return this expression.
        /// </summary>
        /// <param name="operand">The <see cref="Operand" /> property of the result.</param>
        /// <returns>This expression if no children changed, or an expression with the updated children.</returns>
        public UnaryExpression Update(Expression operand) {
            if (operand == Operand) {
                return this;
            }
            return Expression.MakeUnary(NodeType, operand, Type, Method);
        }
    }

    public partial class Expression {

        /// <summary>
        /// Creates a <see cref="UnaryExpression"></see>, given an operand, by calling the appropriate factory method.
        /// </summary>
        /// <param name="unaryType">The <see cref="ExpressionType"></see> that specifies the type of unary operation.</param>
        /// <param name="operand">An <see cref="Expression"></see> that represents the operand.</param>
        /// <param name="type">The <see cref="Type"></see> that specifies the type to be converted to (pass null if not applicable).</param>
        /// <returns>The <see cref="UnaryExpression"></see> that results from calling the appropriate factory method.</returns>
        /// <exception cref="ArgumentException">Thrown when <paramref name="unaryType"/> does not correspond to a unary expression.</exception>
        /// <exception cref="ArgumentNullException">Thrown when <paramref name="operand"/> is null.</exception>
        public static UnaryExpression MakeUnary(ExpressionType unaryType, Expression operand, Type type) {
            return MakeUnary(unaryType, operand, type, null);
        }

        /// <summary>
        /// Creates a <see cref="UnaryExpression"></see>, given an operand and implementing method, by calling the appropriate factory method.
        /// </summary>
        /// <param name="unaryType">The <see cref="ExpressionType"></see> that specifies the type of unary operation.</param>
        /// <param name="operand">An <see cref="Expression"></see> that represents the operand.</param>
        /// <param name="type">The <see cref="Type"></see> that specifies the type to be converted to (pass null if not applicable).</param>
        /// <param name="method">The <see cref="MethodInfo"></see> that represents the implementing method.</param>
        /// <returns>The <see cref="UnaryExpression"></see> that results from calling the appropriate factory method.</returns>
        /// <exception cref="ArgumentException">Thrown when <paramref name="unaryType"/> does not correspond to a unary expression.</exception> 
        /// <exception cref="ArgumentNullException">Thrown when <paramref name="operand"/> is null.</exception>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
        public static UnaryExpression MakeUnary(ExpressionType unaryType, Expression operand, Type type, MethodInfo method) {
            switch (unaryType) {
                case ExpressionType.Negate:
                    return Negate(operand, method);
                case ExpressionType.NegateChecked:
                    return NegateChecked(operand, method);
                case ExpressionType.Not:
                    return Not(operand, method);
                case ExpressionType.IsFalse:
                    return IsFalse(operand, method);
                case ExpressionType.IsTrue:
                    return IsTrue(operand, method);
                case ExpressionType.OnesComplement:
                    return OnesComplement(operand, method);
                case ExpressionType.ArrayLength:
                    return ArrayLength(operand);
                case ExpressionType.Convert:
                    return Convert(operand, type, method);
                case ExpressionType.ConvertChecked:
                    return ConvertChecked(operand, type, method);
                case ExpressionType.Throw:
                    return Throw(operand, type);
                case ExpressionType.TypeAs:
                    return TypeAs(operand, type);
                case ExpressionType.Quote:
                    return Quote(operand);
                case ExpressionType.UnaryPlus:
                    return UnaryPlus(operand, method);
                case ExpressionType.Unbox:
                    return Unbox(operand, type);
                case ExpressionType.Increment:
                    return Increment(operand, method);
                case ExpressionType.Decrement:
                    return Decrement(operand, method);
                case ExpressionType.PreIncrementAssign:
                    return PreIncrementAssign(operand, method);
                case ExpressionType.PostIncrementAssign:
                    return PostIncrementAssign(operand, method);
                case ExpressionType.PreDecrementAssign:
                    return PreDecrementAssign(operand, method);
                case ExpressionType.PostDecrementAssign:
                    return PostDecrementAssign(operand, method);
                default:
                    throw Error.UnhandledUnary(unaryType);
            }
        }

        private static UnaryExpression GetUserDefinedUnaryOperatorOrThrow(ExpressionType unaryType, string name, Expression operand) {
            UnaryExpression u = GetUserDefinedUnaryOperator(unaryType, name, operand);
            if (u != null) {
                ValidateParamswithOperandsOrThrow(u.Method.GetParametersCached()[0].ParameterType, operand.Type, unaryType, name);
                return u;
            }
            throw Error.UnaryOperatorNotDefined(unaryType, operand.Type);
        }

        private static UnaryExpression GetUserDefinedUnaryOperator(ExpressionType unaryType, string name, Expression operand) {
            Type operandType = operand.Type;
            Type[] types = new Type[] { operandType };
            Type nnOperandType = TypeUtils.GetNonNullableType(operandType);
            BindingFlags flags = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
            MethodInfo method = nnOperandType.GetMethodValidated(name, flags, null, types, null);
            if (method != null) {
                return new UnaryExpression(unaryType, operand, method.ReturnType, method);
            }
            // try lifted call
            if (TypeUtils.IsNullableType(operandType)) {
                types[0] = nnOperandType;
                method = nnOperandType.GetMethodValidated(name, flags, null, types, null);
                if (method != null && method.ReturnType.IsValueType && !TypeUtils.IsNullableType(method.ReturnType)) {
                    return new UnaryExpression(unaryType, operand, TypeUtils.GetNullableType(method.ReturnType), method);
                }
            }
            return null;
        }

        private static UnaryExpression GetMethodBasedUnaryOperator(ExpressionType unaryType, Expression operand, MethodInfo method) {
            System.Diagnostics.Debug.Assert(method != null);
            ValidateOperator(method);
            ParameterInfo[] pms = method.GetParametersCached();
            if (pms.Length != 1)
                throw Error.IncorrectNumberOfMethodCallArguments(method);
            if (ParameterIsAssignable(pms[0], operand.Type)) {
                ValidateParamswithOperandsOrThrow(pms[0].ParameterType, operand.Type, unaryType, method.Name);
                return new UnaryExpression(unaryType, operand, method.ReturnType, method);
            }
            // check for lifted call
            if (TypeUtils.IsNullableType(operand.Type) &&
                ParameterIsAssignable(pms[0], TypeUtils.GetNonNullableType(operand.Type)) &&
                method.ReturnType.IsValueType && !TypeUtils.IsNullableType(method.ReturnType)) {
                return new UnaryExpression(unaryType, operand, TypeUtils.GetNullableType(method.ReturnType), method);
            }

            throw Error.OperandTypesDoNotMatchParameters(unaryType, method.Name);
        }

        private static UnaryExpression GetUserDefinedCoercionOrThrow(ExpressionType coercionType, Expression expression, Type convertToType) {
            UnaryExpression u = GetUserDefinedCoercion(coercionType, expression, convertToType);
            if (u != null) {
                return u;
            }
            throw Error.CoercionOperatorNotDefined(expression.Type, convertToType);
        }

        private static UnaryExpression GetUserDefinedCoercion(ExpressionType coercionType, Expression expression, Type convertToType) {
            MethodInfo method = TypeUtils.GetUserDefinedCoercionMethod(expression.Type, convertToType, false);
            if (method != null) {
                return new UnaryExpression(coercionType, expression, convertToType, method);
            } else {
                return null;
            }
        }

        private static UnaryExpression GetMethodBasedCoercionOperator(ExpressionType unaryType, Expression operand, Type convertToType, MethodInfo method) {
            System.Diagnostics.Debug.Assert(method != null);
            ValidateOperator(method);
            ParameterInfo[] pms = method.GetParametersCached();
            if (pms.Length != 1) {
                throw Error.IncorrectNumberOfMethodCallArguments(method);
            }
            if (ParameterIsAssignable(pms[0], operand.Type) && TypeUtils.AreEquivalent(method.ReturnType, convertToType)) {
                return new UnaryExpression(unaryType, operand, method.ReturnType, method);
            }
            // check for lifted call
            if ((TypeUtils.IsNullableType(operand.Type) || TypeUtils.IsNullableType(convertToType)) &&
                ParameterIsAssignable(pms[0], TypeUtils.GetNonNullableType(operand.Type)) &&
                TypeUtils.AreEquivalent(method.ReturnType, TypeUtils.GetNonNullableType(convertToType))) {
                return new UnaryExpression(unaryType, operand, convertToType, method);
            }
            throw Error.OperandTypesDoNotMatchParameters(unaryType, method.Name);
        }

        /// <summary>
        /// Creates a <see cref="UnaryExpression"></see> that represents an arithmetic negation operation.
        /// </summary>
        /// <param name="expression">An <see cref="Expression"></see> to set the <see cref="P:UnaryExpression.Operand"></see> property equal to.</param>
        /// <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>
        /// <exception cref="ArgumentNullException">Thrown when <paramref name="expression"/> is null.</exception>
        /// <exception cref="InvalidOperationException">Thrown when the unary minus operator is not defined for <see cref="P:Expression.Type"></see></exception>
        public static UnaryExpression Negate(Expression expression) {
            return Negate(expression, null);
        }

        /// <summary>
        /// Creates a <see cref="UnaryExpression"></see> that represents an arithmetic negation operation.
        /// </summary>
        /// <param name="expression">An <see cref="Expression"></see> to set the <see cref="P:UnaryExpression.Operand"></see> property equal to.</param>
        /// <param name="method">A <see cref="MethodInfo"></see> to set the <see cref="P:UnaryExpression.Method"></see> property equal to.</param>
        /// <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>
        /// <exception cref="ArgumentNullException">Thrown when <paramref name="expression"/> is null.</exception>
        /// <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>
        /// <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>
        public static UnaryExpression Negate(Expression expression, MethodInfo method) {
            RequiresCanRead(expression, "expression");
            if (method == null) {
                if (TypeUtils.IsArithmetic(expression.Type) && !TypeUtils.IsUnsignedInt(expression.Type)) {
                    return new UnaryExpression(ExpressionType.Negate, expression, expression.Type, null);
                }
                return GetUserDefinedUnaryOperatorOrThrow(ExpressionType.Negate, "op_UnaryNegation", expression);
            }
            return GetMethodBasedUnaryOperator(ExpressionType.Negate, expression, method);
        }

        /// <summary>
        /// Creates a <see cref="UnaryExpression"></see> that represents a unary plus operation.
        /// </summary>
        /// <param name="expression">An <see cref="Expression"></see> to set the <see cref="UnaryExpression.Operand"></see> property equal to.</param>
        /// <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>
        /// <exception cref="ArgumentNullException">Thrown when <paramref name="expression"/> is null.</exception>
        /// <exception cref="InvalidOperationException">Thown when the unary minus operator is not defined for expression.Type.</exception>
        public static UnaryExpression UnaryPlus(Expression expression) {
            return UnaryPlus(expression, null);
        }

        /// <summary>
        /// Creates a <see cref="UnaryExpression"></see> that represents a unary plus operation.
        /// </summary>
        /// <param name="expression">An <see cref="Expression"></see> to set the <see cref="UnaryExpression.Operand"></see> property equal to.</param>
        /// <param name="method">A <see cref="MethodInfo"></see> to set the <see cref="UnaryExpression.Method"></see> property equal to.</param>
        /// <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>
        /// <exception cref="ArgumentNullException">Thrown when <paramref name="expression"/> is null.</exception>
        /// <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>
        /// <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>
        public static UnaryExpression UnaryPlus(Expression expression, MethodInfo method) {
            RequiresCanRead(expression, "expression");
            if (method == null) {
                if (TypeUtils.IsArithmetic(expression.Type)) {
                    return new UnaryExpression(ExpressionType.UnaryPlus, expression, expression.Type, null);
                }
                return GetUserDefinedUnaryOperatorOrThrow(ExpressionType.UnaryPlus, "op_UnaryPlus", expression);
            }
            return GetMethodBasedUnaryOperator(ExpressionType.UnaryPlus, expression, method);
        }

        /// <summary>Creates a <see cref="T:System.Linq.Expressions.UnaryExpression" /> that represents an arithmetic negation operation that has overflow checking.</summary>
        /// <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>
        /// <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>
        /// <exception cref="T:System.ArgumentNullException">
        ///   Thrown when <paramref name="expression" /> is null.</exception>
        /// <exception cref="T:System.InvalidOperationException">Thrown when the unary minus operator is not defined for <paramref name="expression" />.Type.</exception> 
        public static UnaryExpression NegateChecked(Expression expression) {
            return NegateChecked(expression, null);
        }

        ///<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>
        ///<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>
        ///<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>
        ///<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>
        ///<exception cref="T:System.ArgumentNullException">
        ///<paramref name="expression" /> is null.</exception>
        ///<exception cref="T:System.ArgumentException">
        ///<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>
        ///<exception cref="T:System.InvalidOperationException">
        ///<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>
        public static UnaryExpression NegateChecked(Expression expression, MethodInfo method) {
            RequiresCanRead(expression, "expression");
            if (method == null) {
                if (TypeUtils.IsArithmetic(expression.Type) && !TypeUtils.IsUnsignedInt(expression.Type)) {
                    return new UnaryExpression(ExpressionType.NegateChecked, expression, expression.Type, null);
                }
                return GetUserDefinedUnaryOperatorOrThrow(ExpressionType.NegateChecked, "op_UnaryNegation", expression);
            }
            return GetMethodBasedUnaryOperator(ExpressionType.NegateChecked, expression, method);
        }

        ///<summary>Creates a <see cref="T:System.Linq.Expressions.UnaryExpression" /> that represents a bitwise complement operation.</summary>
        ///<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>
        ///<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>
        ///<exception cref="T:System.ArgumentNullException">
        ///<paramref name="expression" /> is null.</exception>
        ///<exception cref="T:System.InvalidOperationException">The unary not operator is not defined for <paramref name="expression" />.Type.</exception>
        public static UnaryExpression Not(Expression expression) {
            return Not(expression, null);
        }

        ///<summary>Creates a <see cref="T:System.Linq.Expressions.UnaryExpression" /> that represents a bitwise complement operation. The implementing method can be specified.</summary>
        ///<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>
        ///<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>
        ///<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>
        ///<exception cref="T:System.ArgumentNullException">
        ///<paramref name="expression" /> is null.</exception>
        ///<exception cref="T:System.ArgumentException">
        ///<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>
        ///<exception cref="T:System.InvalidOperationException">
        ///<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>
        public static UnaryExpression Not(Expression expression, MethodInfo method) {
            RequiresCanRead(expression, "expression");
            if (method == null) {
                if (TypeUtils.IsIntegerOrBool(expression.Type)) {
                    return new UnaryExpression(ExpressionType.Not, expression, expression.Type, null);
                }
                UnaryExpression u = GetUserDefinedUnaryOperator(ExpressionType.Not, "op_LogicalNot", expression);
                if (u != null) {
                    return u;
                }
                return GetUserDefinedUnaryOperatorOrThrow(ExpressionType.Not, "op_OnesComplement", expression);
            }
            return GetMethodBasedUnaryOperator(ExpressionType.Not, expression, method);
        }

        /// <summary>
        /// Returns whether the expression evaluates to false.
        /// </summary>
        /// <param name="expression">An <see cref="T:System.Linq.Expressions.Expression" /> to evaluate.</param>
        /// <returns>An instance of <see cref="UnaryExpression"/>.</returns>
        public static UnaryExpression IsFalse(Expression expression) {
            return IsFalse(expression, null);
        }

        /// <summary>
        /// Returns whether the expression evaluates to false.
        /// </summary>
        ///<param name="expression">An <see cref="T:System.Linq.Expressions.Expression" /> to evaluate.</param>
        ///<param name="method">A <see cref="T:System.Reflection.MethodInfo" /> that represents the implementing method.</param>
        /// <returns>An instance of <see cref="UnaryExpression"/>.</returns>
        public static UnaryExpression IsFalse(Expression expression, MethodInfo method) {
            RequiresCanRead(expression, "expression");
            if (method == null) {
                if (TypeUtils.IsBool(expression.Type)) {
                    return new UnaryExpression(ExpressionType.IsFalse, expression, expression.Type, null);
                }
                return GetUserDefinedUnaryOperatorOrThrow(ExpressionType.IsFalse, "op_False", expression);
            }
            return GetMethodBasedUnaryOperator(ExpressionType.IsFalse, expression, method);
        }

        /// <summary>
        /// Returns whether the expression evaluates to true.
        /// </summary>
        /// <param name="expression">An <see cref="T:System.Linq.Expressions.Expression" /> to evaluate.</param>
        /// <returns>An instance of <see cref="UnaryExpression"/>.</returns>
        public static UnaryExpression IsTrue(Expression expression) {
            return IsTrue(expression, null);
        }

        /// <summary>
        /// Returns whether the expression evaluates to true.
        /// </summary>
        ///<param name="expression">An <see cref="T:System.Linq.Expressions.Expression" /> to evaluate.</param>
        ///<param name="method">A <see cref="T:System.Reflection.MethodInfo" /> that represents the implementing method.</param>
        /// <returns>An instance of <see cref="UnaryExpression"/>.</returns>
        public static UnaryExpression IsTrue(Expression expression, MethodInfo method) {
            RequiresCanRead(expression, "expression");
            if (method == null) {
                if (TypeUtils.IsBool(expression.Type)) {
                    return new UnaryExpression(ExpressionType.IsTrue, expression, expression.Type, null);
                }
                return GetUserDefinedUnaryOperatorOrThrow(ExpressionType.IsTrue, "op_True", expression);
            }
            return GetMethodBasedUnaryOperator(ExpressionType.IsTrue, expression, method);
        }

        /// <summary>
        /// Returns the expression representing the ones complement.
        /// </summary>
        ///<param name="expression">An <see cref="T:System.Linq.Expressions.Expression" />.</param>
        /// <returns>An instance of <see cref="UnaryExpression"/>.</returns>
        public static UnaryExpression OnesComplement(Expression expression) {
            return OnesComplement(expression, null);
        }

        /// <summary>
        /// Returns the expression representing the ones complement.
        /// </summary>
        /// <param name="expression">An <see cref="T:System.Linq.Expressions.Expression" />.</param>
        /// <param name="method">A <see cref="T:System.Reflection.MethodInfo" /> that represents the implementing method.</param>
        /// <returns>An instance of <see cref="UnaryExpression"/>.</returns>
        public static UnaryExpression OnesComplement(Expression expression, MethodInfo method) {
            RequiresCanRead(expression, "expression");
            if (method == null) {
                if (TypeUtils.IsInteger(expression.Type)) {
                    return new UnaryExpression(ExpressionType.OnesComplement, expression, expression.Type, null);
                }
                return GetUserDefinedUnaryOperatorOrThrow(ExpressionType.OnesComplement, "op_OnesComplement", expression);
            }
            return GetMethodBasedUnaryOperator(ExpressionType.OnesComplement, expression, method);
        }

        ///<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>
        ///<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>
        ///<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>
        ///<param name="type">A <see cref="T:System.Type" /> to set the <see cref="P:System.Linq.Expressions.Expression.Type" /> property equal to.</param>
        ///<exception cref="T:System.ArgumentNullException">
        ///<paramref name="expression" /> or <paramref name="type" /> is null.</exception>
        public static UnaryExpression TypeAs(Expression expression, Type type) {
            RequiresCanRead(expression, "expression");
            ContractUtils.RequiresNotNull(type, "type");
            TypeUtils.ValidateType(type);

            if (type.IsValueType && !TypeUtils.IsNullableType(type)) {
                throw Error.IncorrectTypeForTypeAs(type);
            }
            return new UnaryExpression(ExpressionType.TypeAs, expression, type, null);
        }

        /// <summary>
        /// <summary>Creates a <see cref="T:System.Linq.Expressions.UnaryExpression" /> that represents an explicit unboxing.</summary>
        /// </summary>     
        /// <param name="expression">An <see cref="T:System.Linq.Expressions.Expression" /> to unbox.</param>
        /// <param name="type">The new <see cref="T:System.Type" /> of the expression.</param>
        /// <returns>An instance of <see cref="UnaryExpression"/>.</returns>
        public static UnaryExpression Unbox(Expression expression, Type type) {
            RequiresCanRead(expression, "expression");
            ContractUtils.RequiresNotNull(type, "type");
            if (!expression.Type.IsInterface && expression.Type != typeof(object)) {
                throw Error.InvalidUnboxType();
            }
            if (!type.IsValueType) throw Error.InvalidUnboxType();
            TypeUtils.ValidateType(type);
            return new UnaryExpression(ExpressionType.Unbox, expression, type, null);
        }

        ///<summary>Creates a <see cref="T:System.Linq.Expressions.UnaryExpression" /> that represents a conversion operation.</summary>
        ///<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>
        ///<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>
        ///<param name="type">A <see cref="T:System.Type" /> to set the <see cref="P:System.Linq.Expressions.Expression.Type" /> property equal to.</param>
        ///<exception cref="T:System.ArgumentNullException">
        ///<paramref name="expression" /> or <paramref name="type" /> is null.</exception>
        ///<exception cref="T:System.InvalidOperationException">No conversion operator is defined between <paramref name="expression" />.Type and <paramref name="type" />.</exception>
        public static UnaryExpression Convert(Expression expression, Type type) {
            return Convert(expression, type, null);
        }

        ///<summary>Creates a <see cref="T:System.Linq.Expressions.UnaryExpression" /> that represents a conversion operation for which the implementing method is specified.</summary>
        ///<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>
        ///<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>
        ///<param name="type">A <see cref="T:System.Type" /> to set the <see cref="P:System.Linq.Expressions.Expression.Type" /> property equal to.</param>
        ///<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>
        ///<exception cref="T:System.ArgumentNullException">
        ///<paramref name="expression" /> or <paramref name="type" /> is null.</exception>
        ///<exception cref="T:System.ArgumentException">
        ///<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>
        ///<exception cref="T:System.Reflection.AmbiguousMatchException">More than one method that matches the <paramref name="method" /> description was found.</exception>
        ///<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>
        public static UnaryExpression Convert(Expression expression, Type type, MethodInfo method) {
            RequiresCanRead(expression, "expression");
            ContractUtils.RequiresNotNull(type, "type");
            TypeUtils.ValidateType(type);

            if (method == null) {
                if (TypeUtils.HasIdentityPrimitiveOrNullableConversion(expression.Type, type) ||
                    TypeUtils.HasReferenceConversion(expression.Type, type)) {
                    return new UnaryExpression(ExpressionType.Convert, expression, type, null);
                }
                return GetUserDefinedCoercionOrThrow(ExpressionType.Convert, expression, type);
            }
            return GetMethodBasedCoercionOperator(ExpressionType.Convert, expression, type, method);
        }

        ///<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>
        ///<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>
        ///<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>
        ///<param name="type">A <see cref="T:System.Type" /> to set the <see cref="P:System.Linq.Expressions.Expression.Type" /> property equal to.</param>
        ///<exception cref="T:System.ArgumentNullException">
        ///<paramref name="expression" /> or <paramref name="type" /> is null.</exception>
        ///<exception cref="T:System.InvalidOperationException">No conversion operator is defined between <paramref name="expression" />.Type and <paramref name="type" />.</exception>
        public static UnaryExpression ConvertChecked(Expression expression, Type type) {
            return ConvertChecked(expression, type, null);
        }

        ///<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>
        ///<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>
        ///<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>
        ///<param name="type">A <see cref="T:System.Type" /> to set the <see cref="P:System.Linq.Expressions.Expression.Type" /> property equal to.</param>
        ///<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>
        ///<exception cref="T:System.ArgumentNullException">
        ///<paramref name="expression" /> or <paramref name="type" /> is null.</exception>
        ///<exception cref="T:System.ArgumentException">
        ///<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>
        ///<exception cref="T:System.Reflection.AmbiguousMatchException">More than one method that matches the <paramref name="method" /> description was found.</exception>
        ///<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>
        public static UnaryExpression ConvertChecked(Expression expression, Type type, MethodInfo method) {
            RequiresCanRead(expression, "expression");
            ContractUtils.RequiresNotNull(type, "type");
            TypeUtils.ValidateType(type);

            if (method == null) {
                if (TypeUtils.HasIdentityPrimitiveOrNullableConversion(expression.Type, type)) {
                    return new UnaryExpression(ExpressionType.ConvertChecked, expression, type, null);
                }
                if (TypeUtils.HasReferenceConversion(expression.Type, type)) {
                    return new UnaryExpression(ExpressionType.Convert, expression, type, null);
                }
                return GetUserDefinedCoercionOrThrow(ExpressionType.ConvertChecked, expression, type);
            }
            return GetMethodBasedCoercionOperator(ExpressionType.ConvertChecked, expression, type, method);
        }

        ///<summary>Creates a <see cref="T:System.Linq.Expressions.UnaryExpression" /> that represents getting the length of a one-dimensional array.</summary>
        ///<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>
        ///<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>
        ///<exception cref="T:System.ArgumentNullException">
        ///<paramref name="array" /> is null.</exception>
        ///<exception cref="T:System.ArgumentException">
        ///<paramref name="array" />.Type does not represent an array type.</exception>
        public static UnaryExpression ArrayLength(Expression array) {
            ContractUtils.RequiresNotNull(array, "array");
            if (!array.Type.IsArray || !typeof(Array).IsAssignableFrom(array.Type)) {
                throw Error.ArgumentMustBeArray();
            }
            if (array.Type.GetArrayRank() != 1) {
                throw Error.ArgumentMustBeSingleDimensionalArrayType();
            }
            return new UnaryExpression(ExpressionType.ArrayLength, array, typeof(int), null);
        }

        ///<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>
        ///<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>
        ///<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>
        ///<exception cref="T:System.ArgumentNullException">
        ///<paramref name="expression" /> is null.</exception>
        public static UnaryExpression Quote(Expression expression) {
            RequiresCanRead(expression, "expression");
            if (!(expression is LambdaExpression)) throw Error.QuotedExpressionMustBeLambda();
            return new UnaryExpression(ExpressionType.Quote, expression, expression.GetType(), null);
        }

        /// <summary>
        /// Creates a <see cref="T:System.Linq.Expressions.UnaryExpression" /> that represents a rethrowing of an exception.
        /// </summary>
        /// <returns>A <see cref="T:System.Linq.Expressions.UnaryExpression"/> that represents a rethrowing of an exception.</returns>
        public static UnaryExpression Rethrow() {
            return Throw(null);
        }

        /// <summary>
        /// Creates a <see cref="T:System.Linq.Expressions.UnaryExpression" /> that represents a rethrowing of an exception with a given type.
        /// </summary>
        ///<param name="type">The new <see cref="T:System.Type" /> of the expression.</param>
        /// <returns>A <see cref="T:System.Linq.Expressions.UnaryExpression"/> that represents a rethrowing of an exception.</returns>
        public static UnaryExpression Rethrow(Type type) {
            return Throw(null, type);
        }

        /// <summary>
        /// Creates a <see cref="T:System.Linq.Expressions.UnaryExpression" /> that represents a throwing of an exception.
        /// </summary>
        /// <param name="value">An <see cref="T:System.Linq.Expressions.Expression" />.</param>
        /// <returns>A <see cref="T:System.Linq.Expressions.UnaryExpression"/> that represents the exception.</returns>
        public static UnaryExpression Throw(Expression value) {
            return Throw(value, typeof(void));
        }

        /// <summary>
        /// Creates a <see cref="T:System.Linq.Expressions.UnaryExpression" /> that represents a throwing of a value with a given type.
        /// </summary>
        /// <param name="value">An <see cref="T:System.Linq.Expressions.Expression" />.</param>
        /// <param name="type">The new <see cref="T:System.Type" /> of the expression.</param>
        /// <returns>A <see cref="T:System.Linq.Expressions.UnaryExpression"/> that represents the exception.</returns>
        public static UnaryExpression Throw(Expression value, Type type) {
            ContractUtils.RequiresNotNull(type, "type");
            TypeUtils.ValidateType(type);

            if (value != null) {
                RequiresCanRead(value, "value");
                if (value.Type.IsValueType) throw Error.ArgumentMustNotHaveValueType();
            }
            return new UnaryExpression(ExpressionType.Throw, value, type, null);
        }

        /// <summary>
        /// Creates a <see cref="T:System.Linq.Expressions.UnaryExpression" /> that represents the incrementing of the expression by 1.
        /// </summary>
        /// <param name="expression">An <see cref="T:System.Linq.Expressions.Expression"></see> to increment.</param>
        /// <returns>A <see cref="T:System.Linq.Expressions.UnaryExpression"/> that represents the incremented expression.</returns>
        public static UnaryExpression Increment(Expression expression) {
            return Increment(expression, null);
        }

        /// <summary>
        /// Creates a <see cref="T:System.Linq.Expressions.UnaryExpression" /> that represents the incrementing of the expression by 1.
        /// </summary>
        /// <param name="expression">An <see cref="T:System.Linq.Expressions.Expression"></see> to increment.</param>
        ///<param name="method">A <see cref="T:System.Reflection.MethodInfo" /> that represents the implementing method.</param>
        /// <returns>A <see cref="T:System.Linq.Expressions.UnaryExpression"/> that represents the incremented expression.</returns>
        public static UnaryExpression Increment(Expression expression, MethodInfo method) {
            RequiresCanRead(expression, "expression");
            if (method == null) {
                if (TypeUtils.IsArithmetic(expression.Type)) {
                    return new UnaryExpression(ExpressionType.Increment, expression, expression.Type, null);
                }
                return GetUserDefinedUnaryOperatorOrThrow(ExpressionType.Increment, "op_Increment", expression);
            }
            return GetMethodBasedUnaryOperator(ExpressionType.Increment, expression, method);
        }

        /// <summary>
        /// Creates a <see cref="T:System.Linq.Expressions.UnaryExpression" /> that represents the decrementing of the expression by 1.
        /// </summary>
        /// <param name="expression">An <see cref="T:System.Linq.Expressions.Expression"></see> to decrement.</param>
        /// <returns>A <see cref="T:System.Linq.Expressions.UnaryExpression"/> that represents the decremented expression.</returns>
        public static UnaryExpression Decrement(Expression expression) {
            return Decrement(expression, null);
        }

        /// <summary>
        /// Creates a <see cref="T:System.Linq.Expressions.UnaryExpression" /> that represents the decrementing of the expression by 1.
        /// </summary>
        /// <param name="expression">An <see cref="T:System.Linq.Expressions.Expression"></see> to decrement.</param>
        ///<param name="method">A <see cref="T:System.Reflection.MethodInfo" /> that represents the implementing method.</param>
        /// <returns>A <see cref="T:System.Linq.Expressions.UnaryExpression"/> that represents the decremented expression.</returns>
        public static UnaryExpression Decrement(Expression expression, MethodInfo method) {
            RequiresCanRead(expression, "expression");
            if (method == null) {
                if (TypeUtils.IsArithmetic(expression.Type)) {
                    return new UnaryExpression(ExpressionType.Decrement, expression, expression.Type, null);
                }
                return GetUserDefinedUnaryOperatorOrThrow(ExpressionType.Decrement, "op_Decrement", expression);
            }
            return GetMethodBasedUnaryOperator(ExpressionType.Decrement, expression, method);
        }

        /// <summary>
        /// Creates a <see cref="UnaryExpression"/> that increments the expression by 1
        /// and assigns the result back to the expression.
        /// </summary>
        /// <param name="expression">An <see cref="T:System.Linq.Expressions.Expression"></see> to apply the operations on.</param>
        /// <returns>A <see cref="T:System.Linq.Expressions.UnaryExpression"/> that represents the resultant expression.</returns>
        public static UnaryExpression PreIncrementAssign(Expression expression) {
            return MakeOpAssignUnary(ExpressionType.PreIncrementAssign, expression, null);

        }

        /// <summary>
        /// Creates a <see cref="UnaryExpression"/> that increments the expression by 1
        /// and assigns the result back to the expression.
        /// </summary>
        /// <param name="expression">An <see cref="T:System.Linq.Expressions.Expression"></see> to apply the operations on.</param>
        /// <param name="method">A <see cref="T:System.Reflection.MethodInfo" /> that represents the implementing method.</param>
        /// <returns>A <see cref="T:System.Linq.Expressions.UnaryExpression"/> that represents the resultant expression.</returns>
        public static UnaryExpression PreIncrementAssign(Expression expression, MethodInfo method) {
            return MakeOpAssignUnary(ExpressionType.PreIncrementAssign, expression, method);
        }

        /// <summary>
        /// Creates a <see cref="UnaryExpression"/> that decrements the expression by 1
        /// and assigns the result back to the expression.
        /// </summary>
        /// <param name="expression">An <see cref="T:System.Linq.Expressions.Expression"></see> to apply the operations on.</param>
        /// <returns>A <see cref="T:System.Linq.Expressions.UnaryExpression"/> that represents the resultant expression.</returns>
        public static UnaryExpression PreDecrementAssign(Expression expression) {
            return MakeOpAssignUnary(ExpressionType.PreDecrementAssign, expression, null);
        }

        /// <summary>
        /// Creates a <see cref="UnaryExpression"/> that decrements the expression by 1
        /// and assigns the result back to the expression.
        /// </summary>
        /// <param name="expression">An <see cref="T:System.Linq.Expressions.Expression"></see> to apply the operations on.</param>
        /// <param name="method">A <see cref="T:System.Reflection.MethodInfo" /> that represents the implementing method.</param>
        /// <returns>A <see cref="T:System.Linq.Expressions.UnaryExpression"/> that represents the resultant expression.</returns>
        public static UnaryExpression PreDecrementAssign(Expression expression, MethodInfo method) {
            return MakeOpAssignUnary(ExpressionType.PreDecrementAssign, expression, method);
        }

        /// <summary>
        /// Creates a <see cref="UnaryExpression"/> that represents the assignment of the expression 
        /// followed by a subsequent increment by 1 of the original expression.
        /// </summary>
        /// <param name="expression">An <see cref="T:System.Linq.Expressions.Expression"></see> to apply the operations on.</param>
        /// <returns>A <see cref="T:System.Linq.Expressions.UnaryExpression"/> that represents the resultant expression.</returns>
        public static UnaryExpression PostIncrementAssign(Expression expression) {
            return MakeOpAssignUnary(ExpressionType.PostIncrementAssign, expression, null);
        }

        /// <summary>
        /// Creates a <see cref="UnaryExpression"/> that represents the assignment of the expression 
        /// followed by a subsequent increment by 1 of the original expression.
        /// </summary>
        /// <param name="expression">An <see cref="T:System.Linq.Expressions.Expression"></see> to apply the operations on.</param>
        /// <param name="method">A <see cref="T:System.Reflection.MethodInfo" /> that represents the implementing method.</param>
        /// <returns>A <see cref="T:System.Linq.Expressions.UnaryExpression"/> that represents the resultant expression.</returns>
        public static UnaryExpression PostIncrementAssign(Expression expression, MethodInfo method) {
            return MakeOpAssignUnary(ExpressionType.PostIncrementAssign, expression, method);
        }

        /// <summary>
        /// Creates a <see cref="UnaryExpression"/> that represents the assignment of the expression 
        /// followed by a subsequent decrement by 1 of the original expression.
        /// </summary>
        /// <param name="expression">An <see cref="T:System.Linq.Expressions.Expression"></see> to apply the operations on.</param>
        /// <returns>A <see cref="T:System.Linq.Expressions.UnaryExpression"/> that represents the resultant expression.</returns>
        public static UnaryExpression PostDecrementAssign(Expression expression) {
            return MakeOpAssignUnary(ExpressionType.PostDecrementAssign, expression, null);
        }

        /// <summary>
        /// Creates a <see cref="UnaryExpression"/> that represents the assignment of the expression 
        /// followed by a subsequent decrement by 1 of the original expression.
        /// </summary>
        /// <param name="expression">An <see cref="T:System.Linq.Expressions.Expression"></see> to apply the operations on.</param>
        /// <param name="method">A <see cref="T:System.Reflection.MethodInfo" /> that represents the implementing method.</param>
        /// <returns>A <see cref="T:System.Linq.Expressions.UnaryExpression"/> that represents the resultant expression.</returns>
        public static UnaryExpression PostDecrementAssign(Expression expression, MethodInfo method) {
            return MakeOpAssignUnary(ExpressionType.PostDecrementAssign, expression, method);
        }

        private static UnaryExpression MakeOpAssignUnary(ExpressionType kind, Expression expression, MethodInfo method) {
            RequiresCanRead(expression, "expression");
            RequiresCanWrite(expression, "expression");

            UnaryExpression result;
            if (method == null) {
                if (TypeUtils.IsArithmetic(expression.Type)) {
                    return new UnaryExpression(kind, expression, expression.Type, null);
                }
                string name;
                if (kind == ExpressionType.PreIncrementAssign || kind == ExpressionType.PostIncrementAssign) {
                    name = "op_Increment";
                } else {
                    name = "op_Decrement";
                }
                result = GetUserDefinedUnaryOperatorOrThrow(kind, name, expression);
            } else {
                result = GetMethodBasedUnaryOperator(kind, expression, method);
            }
            // return type must be assignable back to the operand type
            if (!TypeUtils.AreReferenceAssignable(expression.Type, result.Type)) {
                throw Error.UserDefinedOpMustHaveValidReturnType(kind, method.Name);
            }
            return result;
        }
    }
}
www.java2v.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.