UnaryExpression.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / Core / Microsoft / Scripting / Ast / UnaryExpression.cs / 1305376 / 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.Diagnostics; 
using System.Dynamic.Utils; 
using System.Reflection;
using System.Runtime.CompilerServices; 

#if SILVERLIGHT
using System.Core;
#endif 

namespace System.Linq.Expressions { 
 
    /// 
    /// Represents an expression that has a unary operator. 
    /// 
#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; 
        } 

        ///  
        /// Gets the static type of the expression that this  represents. (Inherited from .)
        /// 
        /// The  that represents the static type of the expression.
        public sealed override Type Type { 
            get { return _type; }
        } 
 
        /// 
        /// Returns the node type of this . (Inherited from .) 
        /// 
        /// The  that represents this expression.
        public sealed override ExpressionType NodeType {
            get { return _nodeType; } 
        }
 
        ///  
        /// Gets the operand of the unary operation.
        ///  
        ///  An  that represents the operand of the unary operation.
        public Expression Operand {
            get { return _operand; }
        } 

        ///  
        /// Gets the implementing method for the unary operation. 
        /// 
        /// The  that represents the implementing method. 
        public MethodInfo Method {
            get { return _method; }
        }
 
        /// 
        /// Gets a value that indicates whether the expression tree node represents a lifted call to an operator. 
        ///  
        /// true if the node represents a lifted call; otherwise, false.
        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;
            }
        } 

        ///  
        /// 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. 
        /// 
        /// true if the operator's return type is lifted to a nullable type; otherwise, false. 
        public bool IsLiftedToNull {
            get {
                return IsLifted && TypeUtils.IsNullableType(this.Type);
            } 
        }
 
        ///  
        /// Dispatches to the specific visit method for this node type.
        ///  
        protected internal override Expression Accept(ExpressionVisitor visitor) {
            return visitor.VisitUnary(this);
        }
 
        /// 
        /// Gets a value that indicates whether the expression tree node can be reduced. 
        ///  
        public override bool CanReduce {
            get { 
                switch (_nodeType) {
                    case ExpressionType.PreIncrementAssign:
                    case ExpressionType.PreDecrementAssign:
                    case ExpressionType.PostIncrementAssign: 
                    case ExpressionType.PostDecrementAssign:
                        return true; 
                } 
                return false;
            } 
        }

        /// 
        /// 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. 
        /// 
        /// The reduced expression. 
        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(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(temps), new TrueReadOnlyCollection(block)); 
        } 

        ///  
        /// 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.
        ///  
        /// The  property of the result.
        /// This expression if no children changed, or an expression with the updated children. 
        public UnaryExpression Update(Expression operand) { 
            if (operand == Operand) {
                return this; 
            }
            return Expression.MakeUnary(NodeType, operand, Type, Method);
        }
    } 

    public partial class Expression { 
 
        /// 
        /// Creates a , given an operand, by calling the appropriate factory method. 
        /// 
        /// The  that specifies the type of unary operation.
        /// An  that represents the operand.
        /// The  that specifies the type to be converted to (pass null if not applicable). 
        /// The  that results from calling the appropriate factory method.
        /// Thrown when  does not correspond to a unary expression. 
        /// Thrown when  is null. 
        public static UnaryExpression MakeUnary(ExpressionType unaryType, Expression operand, Type type) {
            return MakeUnary(unaryType, operand, type, null); 
        }

        /// 
        /// Creates a , given an operand and implementing method, by calling the appropriate factory method. 
        /// 
        /// The  that specifies the type of unary operation. 
        /// An  that represents the operand. 
        /// The  that specifies the type to be converted to (pass null if not applicable).
        /// The  that represents the implementing method. 
        /// The  that results from calling the appropriate factory method.
        /// Thrown when  does not correspond to a unary expression.
        /// Thrown when  is null.
        [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);
        } 

        /// 
        /// Creates a  that represents an arithmetic negation operation.
        ///  
        /// An  to set the  property equal to.
        /// A  that has the  property equal to  and the  properties set to the specified value. 
        /// Thrown when  is null. 
        /// Thrown when the unary minus operator is not defined for 
        public static UnaryExpression Negate(Expression expression) { 
            return Negate(expression, null);
        }

        ///  
        /// Creates a  that represents an arithmetic negation operation.
        ///  
        /// An  to set the  property equal to. 
        /// A  to set the  property equal to.
        /// A  that has the  property equal to  and the  and  properties set to the specified value. 
        /// Thrown when  is null.
        /// Thrown when  is not null and the method it represents returns void, is not static (Shared in Visual Basic), or does not take exactly one argument.
        /// Thown when  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.
        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);
        } 

        ///  
        /// Creates a  that represents a unary plus operation. 
        /// 
        /// An  to set the  property equal to. 
        /// A  that has the  property equal to  and the  property set to the specified value.
        /// Thrown when  is null.
        /// Thown when the unary minus operator is not defined for expression.Type.
        public static UnaryExpression UnaryPlus(Expression expression) { 
            return UnaryPlus(expression, null);
        } 
 
        /// 
        /// Creates a  that represents a unary plus operation. 
        /// 
        /// An  to set the  property equal to.
        /// A  to set the  property equal to.
        /// A  that has the  property equal to  and the  and property set to the specified value. 
        /// Thrown when  is null.
        /// Thrown when  is not null and the method it represents returns void, is not static (Shared in Visual Basic), or does not take exactly one argument. 
        /// Thown when  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. 
        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); 
        }
 
        /// Creates a  that represents an arithmetic negation operation that has overflow checking.
        /// A  that has the  property equal to  and the  property set to the specified value.
        /// An  to set the  property equal to.
        ///  
        ///   Thrown when  is null.
        /// Thrown when the unary minus operator is not defined for .Type. 
        public static UnaryExpression NegateChecked(Expression expression) { 
            return NegateChecked(expression, null);
        } 

        ///Creates a  that represents an arithmetic negation operation that has overflow checking. The implementing method can be specified.
        ///A  that has the  property equal to  and the  and  properties set to the specified values.
        ///An  to set the  property equal to. 
        ///A  to set the  property equal to.
        /// 
        /// is null. 
        ///
        /// is not null and the method it represents returns void, is not static (Shared in Visual Basic), or does not take exactly one argument. 
        ///
        /// is null and the unary minus operator is not defined for .Type.-or-.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 .
        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);
        }
 
        ///Creates a  that represents a bitwise complement operation.
        ///A  that has the  property equal to  and the  property set to the specified value. 
        ///An  to set the  property equal to. 
        ///
        /// is null. 
        ///The unary not operator is not defined for .Type.
        public static UnaryExpression Not(Expression expression) {
            return Not(expression, null);
        } 

        ///Creates a  that represents a bitwise complement operation. The implementing method can be specified. 
        ///A  that has the  property equal to  and the  and  properties set to the specified values. 
        ///An  to set the  property equal to.
        ///A  to set the  property equal to. 
        ///
        /// is null.
        ///
        /// is not null and the method it represents returns void, is not static (Shared in Visual Basic), or does not take exactly one argument. 
        ///
        /// is null and the unary not operator is not defined for .Type.-or-.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 . 
        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);
        }

        ///  
        /// Returns whether the expression evaluates to false.
        ///  
        /// An  to evaluate. 
        /// An instance of .
        public static UnaryExpression IsFalse(Expression expression) { 
            return IsFalse(expression, null);
        }

        ///  
        /// Returns whether the expression evaluates to false.
        ///  
        ///An  to evaluate. 
        ///A  that represents the implementing method.
        /// An instance of . 
        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); 
        }

        /// 
        /// Returns whether the expression evaluates to true. 
        /// 
        /// An  to evaluate. 
        /// An instance of . 
        public static UnaryExpression IsTrue(Expression expression) {
            return IsTrue(expression, null); 
        }

        /// 
        /// Returns whether the expression evaluates to true. 
        /// 
        ///An  to evaluate. 
        ///A  that represents the implementing method. 
        /// An instance of .
        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);
        } 

        /// 
        /// Returns the expression representing the ones complement.
        ///  
        ///An .
        /// An instance of . 
        public static UnaryExpression OnesComplement(Expression expression) { 
            return OnesComplement(expression, null);
        } 

        /// 
        /// Returns the expression representing the ones complement.
        ///  
        /// An .
        /// A  that represents the implementing method. 
        /// An instance of . 
        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); 
        }
 
        ///Creates a  that represents an explicit reference or boxing conversion where null is supplied if the conversion fails.
        ///A  that has the  property equal to  and the  and  properties set to the specified values.
        ///An  to set the  property equal to.
        ///A  to set the  property equal to. 
        ///
        /// or  is null. 
        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); 
        } 

        ///  
        /// Creates a  that represents an explicit unboxing.
        /// 
        /// An  to unbox.
        /// The new  of the expression. 
        /// An instance of .
        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);
        } 
 
        ///Creates a  that represents a conversion operation.
        ///A  that has the  property equal to  and the  and  properties set to the specified values. 
        ///An  to set the  property equal to.
        ///A  to set the  property equal to.
        ///
        /// or  is null. 
        ///No conversion operator is defined between .Type and .
        public static UnaryExpression Convert(Expression expression, Type type) { 
            return Convert(expression, type, null); 
        }
 
        ///Creates a  that represents a conversion operation for which the implementing method is specified.
        ///A  that has the  property equal to  and the , , and  properties set to the specified values.
        ///An  to set the  property equal to.
        ///A  to set the  property equal to. 
        ///A  to set the  property equal to.
        /// 
        /// or  is null. 
        ///
        /// is not null and the method it represents returns void, is not static (Shared in Visual Basic), or does not take exactly one argument. 
        ///More than one method that matches the  description was found.
        ///No conversion operator is defined between .Type and .-or-.Type is not assignable to the argument type of the method represented by .-or-The return type of the method represented by  is not assignable to .-or-.Type or  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 .
        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); 
        } 

        ///Creates a  that represents a conversion operation that throws an exception if the target type is overflowed. 
        ///A  that has the  property equal to  and the  and  properties set to the specified values.
        ///An  to set the  property equal to.
        ///A  to set the  property equal to.
        /// 
        /// or  is null.
        ///No conversion operator is defined between .Type and . 
        public static UnaryExpression ConvertChecked(Expression expression, Type type) { 
            return ConvertChecked(expression, type, null);
        } 

        ///Creates a  that represents a conversion operation that throws an exception if the target type is overflowed and for which the implementing method is specified.
        ///A  that has the  property equal to  and the , , and  properties set to the specified values.
        ///An  to set the  property equal to. 
        ///A  to set the  property equal to.
        ///A  to set the  property equal to. 
        /// 
        /// or  is null.
        /// 
        /// is not null and the method it represents returns void, is not static (Shared in Visual Basic), or does not take exactly one argument.
        ///More than one method that matches the  description was found.
        ///No conversion operator is defined between .Type and .-or-.Type is not assignable to the argument type of the method represented by .-or-The return type of the method represented by  is not assignable to .-or-.Type or  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 .
        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); 
        }

        ///Creates a  that represents getting the length of a one-dimensional array.
        ///A  that has the  property equal to  and the  property equal to . 
        ///An  to set the  property equal to.
        /// 
        /// is null. 
        ///
        ///.Type does not represent an array type. 
        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); 
        }

        ///Creates a  that represents an expression that has a constant value of type .
        ///A  that has the  property equal to  and the  property set to the specified value. 
        ///An  to set the  property equal to.
        /// 
        /// is null. 
        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);
        }
 
        /// 
        /// Creates a  that represents a rethrowing of an exception. 
        ///  
        /// A  that represents a rethrowing of an exception.
        public static UnaryExpression Rethrow() { 
            return Throw(null);
        }

        ///  
        /// Creates a  that represents a rethrowing of an exception with a given type.
        ///  
        ///The new  of the expression. 
        /// A  that represents a rethrowing of an exception.
        public static UnaryExpression Rethrow(Type type) { 
            return Throw(null, type);
        }

        ///  
        /// Creates a  that represents a throwing of an exception.
        ///  
        /// An . 
        /// A  that represents the exception.
        public static UnaryExpression Throw(Expression value) { 
            return Throw(value, typeof(void));
        }

        ///  
        /// Creates a  that represents a throwing of a value with a given type.
        ///  
        /// An . 
        /// The new  of the expression.
        /// A  that represents the exception. 
        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); 
        }

        /// 
        /// Creates a  that represents the incrementing of the expression by 1. 
        /// 
        /// An  to increment. 
        /// A  that represents the incremented expression. 
        public static UnaryExpression Increment(Expression expression) {
            return Increment(expression, null); 
        }

        /// 
        /// Creates a  that represents the incrementing of the expression by 1. 
        /// 
        /// An  to increment. 
        ///A  that represents the implementing method. 
        /// A  that represents the incremented expression.
        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);
        } 

        /// 
        /// Creates a  that represents the decrementing of the expression by 1.
        ///  
        /// An  to decrement.
        /// A  that represents the decremented expression. 
        public static UnaryExpression Decrement(Expression expression) { 
            return Decrement(expression, null);
        } 

        /// 
        /// Creates a  that represents the decrementing of the expression by 1.
        ///  
        /// An  to decrement.
        ///A  that represents the implementing method. 
        /// A  that represents the decremented expression. 
        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); 
        }
 
        /// 
        /// Creates a  that increments the expression by 1
        /// and assigns the result back to the expression.
        ///  
        /// An  to apply the operations on.
        /// A  that represents the resultant expression. 
        public static UnaryExpression PreIncrementAssign(Expression expression) { 
            return MakeOpAssignUnary(ExpressionType.PreIncrementAssign, expression, null);
 
        }

        /// 
        /// Creates a  that increments the expression by 1 
        /// and assigns the result back to the expression.
        ///  
        /// An  to apply the operations on. 
        /// A  that represents the implementing method.
        /// A  that represents the resultant expression. 
        public static UnaryExpression PreIncrementAssign(Expression expression, MethodInfo method) {
            return MakeOpAssignUnary(ExpressionType.PreIncrementAssign, expression, method);
        }
 
        /// 
        /// Creates a  that decrements the expression by 1 
        /// and assigns the result back to the expression. 
        /// 
        /// An  to apply the operations on. 
        /// A  that represents the resultant expression.
        public static UnaryExpression PreDecrementAssign(Expression expression) {
            return MakeOpAssignUnary(ExpressionType.PreDecrementAssign, expression, null);
        } 

        ///  
        /// Creates a  that decrements the expression by 1 
        /// and assigns the result back to the expression.
        ///  
        /// An  to apply the operations on.
        /// A  that represents the implementing method.
        /// A  that represents the resultant expression.
        public static UnaryExpression PreDecrementAssign(Expression expression, MethodInfo method) { 
            return MakeOpAssignUnary(ExpressionType.PreDecrementAssign, expression, method);
        } 
 
        /// 
        /// Creates a  that represents the assignment of the expression 
        /// followed by a subsequent increment by 1 of the original expression.
        /// 
        /// An  to apply the operations on.
        /// A  that represents the resultant expression. 
        public static UnaryExpression PostIncrementAssign(Expression expression) {
            return MakeOpAssignUnary(ExpressionType.PostIncrementAssign, expression, null); 
        } 

        ///  
        /// Creates a  that represents the assignment of the expression
        /// followed by a subsequent increment by 1 of the original expression.
        /// 
        /// An  to apply the operations on. 
        /// A  that represents the implementing method.
        /// A  that represents the resultant expression. 
        public static UnaryExpression PostIncrementAssign(Expression expression, MethodInfo method) { 
            return MakeOpAssignUnary(ExpressionType.PostIncrementAssign, expression, method);
        } 

        /// 
        /// Creates a  that represents the assignment of the expression
        /// followed by a subsequent decrement by 1 of the original expression. 
        /// 
        /// An  to apply the operations on. 
        /// A  that represents the resultant expression. 
        public static UnaryExpression PostDecrementAssign(Expression expression) {
            return MakeOpAssignUnary(ExpressionType.PostDecrementAssign, expression, null); 
        }

        /// 
        /// Creates a  that represents the assignment of the expression 
        /// followed by a subsequent decrement by 1 of the original expression.
        ///  
        /// An  to apply the operations on. 
        /// A  that represents the implementing method.
        /// A  that represents the resultant expression. 
        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;
        }
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK