TypeBinaryExpression.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / Core / Microsoft / Scripting / Ast / TypeBinaryExpression.cs / 1305376 / TypeBinaryExpression.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; 

#if SILVERLIGHT 
using System.Core;
#endif

namespace System.Linq.Expressions { 
    /// 
    /// Represents an operation between an expression and a type. 
    ///  
#if !SILVERLIGHT
    [DebuggerTypeProxy(typeof(Expression.TypeBinaryExpressionProxy))] 
#endif
    public sealed class TypeBinaryExpression : Expression {
        private readonly Expression _expression;
        private readonly Type _typeOperand; 
        private readonly ExpressionType _nodeKind;
 
        internal TypeBinaryExpression(Expression expression, Type typeOperand, ExpressionType nodeKind) { 
            _expression = expression;
            _typeOperand = typeOperand; 
            _nodeKind = nodeKind;
        }

        ///  
        /// Gets the static type of the expression that this  represents.
        ///  
        /// The  that represents the static type of the expression. 
        public sealed override Type Type {
            get { return typeof(bool); } 
        }

        /// 
        /// Returns the node type of this Expression. Extension nodes should return 
        /// ExpressionType.Extension when overriding this method.
        ///  
        /// The  of the expression. 
        public sealed override ExpressionType NodeType {
            get { return _nodeKind; } 
        }

        /// 
        /// Gets the expression operand of a type test operation. 
        /// 
        public Expression Expression { 
            get { return _expression; } 
        }
 
        /// 
        /// Gets the type operand of a type test operation.
        /// 
        public Type TypeOperand { 
            get { return _typeOperand; }
        } 
 
        #region Reduce TypeEqual
 
        internal Expression ReduceTypeEqual() {
            Type cType = Expression.Type;

            // For value types (including Void, but not nullables), we can 
            // determine the result now
            if (cType.IsValueType && !cType.IsNullableType()) { 
                return Expression.Block(Expression, Expression.Constant(cType == _typeOperand.GetNonNullableType())); 
            }
 
            // Can check the value right now for constants.
            if (Expression.NodeType == ExpressionType.Constant) {
                return ReduceConstantTypeEqual();
            } 

            // If the operand type is a sealed reference type or a nullable 
            // type, it will match if value is not null 
            if (cType.IsSealed && (cType == _typeOperand)) {
                if (cType.IsNullableType()) { 
                    return Expression.NotEqual(Expression, Expression.Constant(null, Expression.Type));
                } else {
                    return Expression.ReferenceNotEqual(Expression, Expression.Constant(null, Expression.Type));
                } 
            }
 
            // expression is a ByVal parameter. Can safely reevaluate. 
            var parameter = Expression as ParameterExpression;
            if (parameter != null && !parameter.IsByRef) { 
                return ByValParameterTypeEqual(parameter);
            }

            // Create a temp so we only evaluate the left side once 
            parameter = Expression.Parameter(typeof(object));
 
            // Convert to object if necessary 
            var expression = Expression;
            if (!TypeUtils.AreReferenceAssignable(typeof(object), expression.Type)) { 
                expression = Expression.Convert(expression, typeof(object));
            }

            return Expression.Block( 
                new[] { parameter },
                Expression.Assign(parameter, expression), 
                ByValParameterTypeEqual(parameter) 
            );
        } 

        // Helper that is used when re-eval of LHS is safe.
        private Expression ByValParameterTypeEqual(ParameterExpression value) {
            Expression getType = Expression.Call(value, typeof(object).GetMethod("GetType")); 

            // In remoting scenarios, obj.GetType() can return an interface. 
            // But there's a bug in the JIT32's optimized "obj.GetType() == 
            // typeof(ISomething)" codegen, causing it to always return false.
            // We workaround the bug by generating different, less optimal IL 
            // if TypeOperand is an interface.
            if (_typeOperand.IsInterface) {
                var temp = Expression.Parameter(typeof(Type));
                getType = Expression.Block(new[] { temp }, Expression.Assign(temp, getType), temp); 
            }
 
            // We use reference equality when comparing to null for correctness 
            // (don't invoke a user defined operator), and reference equality
            // on types for performance (so the JIT can optimize the IL). 
            return Expression.AndAlso(
                Expression.ReferenceNotEqual(value, Expression.Constant(null)),
                Expression.ReferenceEqual(
                    getType, 
                    Expression.Constant(_typeOperand.GetNonNullableType(), typeof(Type))
                ) 
            ); 
        }
 
        private Expression ReduceConstantTypeEqual() {
            ConstantExpression ce = Expression as ConstantExpression;
            //TypeEqual(null, T) always returns false.
            if (ce.Value == null) { 
                return Expression.Constant(false);
            } else { 
                return Expression.Constant(_typeOperand.GetNonNullableType() == ce.Value.GetType()); 
            }
        } 

        #endregion

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

        /// 
        /// 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 TypeBinaryExpression Update(Expression expression) { 
            if (expression == Expression) {
                return this;
            }
            if (NodeType == ExpressionType.TypeIs) { 
                return Expression.TypeIs(expression, TypeOperand);
            } 
            return Expression.TypeEqual(expression, TypeOperand); 
        }
    } 

    public partial class Expression {
        /// 
        /// Creates a . 
        /// 
        /// An  to set the  property equal to. 
        /// A  to set the  property equal to. 
        /// A  for which the  property is equal to  and for which the  and  properties are set to the specified values.
        public static TypeBinaryExpression TypeIs(Expression expression, Type type) { 
            RequiresCanRead(expression, "expression");
            ContractUtils.RequiresNotNull(type, "type");
            if (type.IsByRef) throw Error.TypeMustNotBeByRef();
 
            return new TypeBinaryExpression(expression, type, ExpressionType.TypeIs);
        } 
 
        /// 
        /// Creates a  that compares run-time type identity. 
        /// 
        /// An  to set the  property equal to.
        /// A  to set the  property equal to.
        /// A  for which the  property is equal to  and for which the  and  properties are set to the specified values. 
        public static TypeBinaryExpression TypeEqual(Expression expression, Type type) {
            RequiresCanRead(expression, "expression"); 
            ContractUtils.RequiresNotNull(type, "type"); 
            if (type.IsByRef) throw Error.TypeMustNotBeByRef();
 
            return new TypeBinaryExpression(expression, type, ExpressionType.TypeEqual);
        }
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
/* **************************************************************************** 
 *
 * 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; 

#if SILVERLIGHT 
using System.Core;
#endif

namespace System.Linq.Expressions { 
    /// 
    /// Represents an operation between an expression and a type. 
    ///  
#if !SILVERLIGHT
    [DebuggerTypeProxy(typeof(Expression.TypeBinaryExpressionProxy))] 
#endif
    public sealed class TypeBinaryExpression : Expression {
        private readonly Expression _expression;
        private readonly Type _typeOperand; 
        private readonly ExpressionType _nodeKind;
 
        internal TypeBinaryExpression(Expression expression, Type typeOperand, ExpressionType nodeKind) { 
            _expression = expression;
            _typeOperand = typeOperand; 
            _nodeKind = nodeKind;
        }

        ///  
        /// Gets the static type of the expression that this  represents.
        ///  
        /// The  that represents the static type of the expression. 
        public sealed override Type Type {
            get { return typeof(bool); } 
        }

        /// 
        /// Returns the node type of this Expression. Extension nodes should return 
        /// ExpressionType.Extension when overriding this method.
        ///  
        /// The  of the expression. 
        public sealed override ExpressionType NodeType {
            get { return _nodeKind; } 
        }

        /// 
        /// Gets the expression operand of a type test operation. 
        /// 
        public Expression Expression { 
            get { return _expression; } 
        }
 
        /// 
        /// Gets the type operand of a type test operation.
        /// 
        public Type TypeOperand { 
            get { return _typeOperand; }
        } 
 
        #region Reduce TypeEqual
 
        internal Expression ReduceTypeEqual() {
            Type cType = Expression.Type;

            // For value types (including Void, but not nullables), we can 
            // determine the result now
            if (cType.IsValueType && !cType.IsNullableType()) { 
                return Expression.Block(Expression, Expression.Constant(cType == _typeOperand.GetNonNullableType())); 
            }
 
            // Can check the value right now for constants.
            if (Expression.NodeType == ExpressionType.Constant) {
                return ReduceConstantTypeEqual();
            } 

            // If the operand type is a sealed reference type or a nullable 
            // type, it will match if value is not null 
            if (cType.IsSealed && (cType == _typeOperand)) {
                if (cType.IsNullableType()) { 
                    return Expression.NotEqual(Expression, Expression.Constant(null, Expression.Type));
                } else {
                    return Expression.ReferenceNotEqual(Expression, Expression.Constant(null, Expression.Type));
                } 
            }
 
            // expression is a ByVal parameter. Can safely reevaluate. 
            var parameter = Expression as ParameterExpression;
            if (parameter != null && !parameter.IsByRef) { 
                return ByValParameterTypeEqual(parameter);
            }

            // Create a temp so we only evaluate the left side once 
            parameter = Expression.Parameter(typeof(object));
 
            // Convert to object if necessary 
            var expression = Expression;
            if (!TypeUtils.AreReferenceAssignable(typeof(object), expression.Type)) { 
                expression = Expression.Convert(expression, typeof(object));
            }

            return Expression.Block( 
                new[] { parameter },
                Expression.Assign(parameter, expression), 
                ByValParameterTypeEqual(parameter) 
            );
        } 

        // Helper that is used when re-eval of LHS is safe.
        private Expression ByValParameterTypeEqual(ParameterExpression value) {
            Expression getType = Expression.Call(value, typeof(object).GetMethod("GetType")); 

            // In remoting scenarios, obj.GetType() can return an interface. 
            // But there's a bug in the JIT32's optimized "obj.GetType() == 
            // typeof(ISomething)" codegen, causing it to always return false.
            // We workaround the bug by generating different, less optimal IL 
            // if TypeOperand is an interface.
            if (_typeOperand.IsInterface) {
                var temp = Expression.Parameter(typeof(Type));
                getType = Expression.Block(new[] { temp }, Expression.Assign(temp, getType), temp); 
            }
 
            // We use reference equality when comparing to null for correctness 
            // (don't invoke a user defined operator), and reference equality
            // on types for performance (so the JIT can optimize the IL). 
            return Expression.AndAlso(
                Expression.ReferenceNotEqual(value, Expression.Constant(null)),
                Expression.ReferenceEqual(
                    getType, 
                    Expression.Constant(_typeOperand.GetNonNullableType(), typeof(Type))
                ) 
            ); 
        }
 
        private Expression ReduceConstantTypeEqual() {
            ConstantExpression ce = Expression as ConstantExpression;
            //TypeEqual(null, T) always returns false.
            if (ce.Value == null) { 
                return Expression.Constant(false);
            } else { 
                return Expression.Constant(_typeOperand.GetNonNullableType() == ce.Value.GetType()); 
            }
        } 

        #endregion

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

        /// 
        /// 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 TypeBinaryExpression Update(Expression expression) { 
            if (expression == Expression) {
                return this;
            }
            if (NodeType == ExpressionType.TypeIs) { 
                return Expression.TypeIs(expression, TypeOperand);
            } 
            return Expression.TypeEqual(expression, TypeOperand); 
        }
    } 

    public partial class Expression {
        /// 
        /// Creates a . 
        /// 
        /// An  to set the  property equal to. 
        /// A  to set the  property equal to. 
        /// A  for which the  property is equal to  and for which the  and  properties are set to the specified values.
        public static TypeBinaryExpression TypeIs(Expression expression, Type type) { 
            RequiresCanRead(expression, "expression");
            ContractUtils.RequiresNotNull(type, "type");
            if (type.IsByRef) throw Error.TypeMustNotBeByRef();
 
            return new TypeBinaryExpression(expression, type, ExpressionType.TypeIs);
        } 
 
        /// 
        /// Creates a  that compares run-time type identity. 
        /// 
        /// An  to set the  property equal to.
        /// A  to set the  property equal to.
        /// A  for which the  property is equal to  and for which the  and  properties are set to the specified values. 
        public static TypeBinaryExpression TypeEqual(Expression expression, Type type) {
            RequiresCanRead(expression, "expression"); 
            ContractUtils.RequiresNotNull(type, "type"); 
            if (type.IsByRef) throw Error.TypeMustNotBeByRef();
 
            return new TypeBinaryExpression(expression, type, ExpressionType.TypeEqual);
        }
    }
} 

// 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