File: System\Linq\Expressions\ConstantExpression.cs
Web Access
Project: src\src\libraries\System.Linq.Expressions\src\System.Linq.Expressions.csproj (System.Linq.Expressions)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System.Diagnostics;
using System.Dynamic.Utils;
 
namespace System.Linq.Expressions
{
    /// <summary>
    /// Represents an expression that has a constant value.
    /// </summary>
    [DebuggerTypeProxy(typeof(ConstantExpressionProxy))]
    public class ConstantExpression : Expression
    {
        internal ConstantExpression(object? value)
        {
            Value = value;
        }
 
        /// <summary>
        /// Gets the static type of the expression that this <see cref="Expression"/> represents.
        /// </summary>
        /// <returns>The <see cref="System.Type"/> that represents the static type of the expression.</returns>
        public override Type Type
        {
            get
            {
                if (Value == null)
                {
                    return typeof(object);
                }
 
                return Value.GetType();
            }
        }
 
        /// <summary>
        /// Returns the node type of this Expression. Extension nodes should return
        /// ExpressionType.Extension when overriding this method.
        /// </summary>
        /// <returns>The <see cref="ExpressionType"/> of the expression.</returns>
        public sealed override ExpressionType NodeType => ExpressionType.Constant;
 
        /// <summary>
        /// Gets the value of the constant expression.
        /// </summary>
        public object? Value { get; }
 
        /// <summary>
        /// Dispatches to the specific visit method for this node type.
        /// </summary>
        protected internal override Expression Accept(ExpressionVisitor visitor)
        {
            return visitor.VisitConstant(this);
        }
    }
 
    internal sealed class TypedConstantExpression : ConstantExpression
    {
        internal TypedConstantExpression(object? value, Type type)
            : base(value)
        {
            Type = type;
        }
 
        public sealed override Type Type { get; }
    }
 
    public partial class Expression
    {
        /// <summary>
        /// Creates a <see cref="ConstantExpression"/> that has the <see cref="ConstantExpression.Value"/> property set to the specified value. .
        /// </summary>
        /// <param name="value">An <see cref="object"/> to set the <see cref="ConstantExpression.Value"/> property equal to.</param>
        /// <returns>
        /// A <see cref="ConstantExpression"/> that has the <see cref="NodeType"/> property equal to
        /// <see cref="ExpressionType.Constant"/> and the <see cref="ConstantExpression.Value"/> property set to the specified value.
        /// </returns>
        public static ConstantExpression Constant(object? value)
        {
            return new ConstantExpression(value);
        }
 
        /// <summary>
        /// Creates a <see cref="ConstantExpression"/> that has the <see cref="ConstantExpression.Value"/>
        /// and <see cref="ConstantExpression.Type"/> properties set to the specified values. .
        /// </summary>
        /// <param name="value">An <see cref="object"/> to set the <see cref="ConstantExpression.Value"/> property equal to.</param>
        /// <param name="type">A <see cref="Type"/> to set the <see cref="Type"/> property equal to.</param>
        /// <returns>
        /// A <see cref="ConstantExpression"/> that has the <see cref="NodeType"/> property equal to
        /// <see cref="ExpressionType.Constant"/> and the <see cref="ConstantExpression.Value"/> and
        /// <see cref="Type"/> properties set to the specified values.
        /// </returns>
        public static ConstantExpression Constant(object? value, Type type)
        {
            ArgumentNullException.ThrowIfNull(type);
            TypeUtils.ValidateType(type, nameof(type));
            if (value == null)
            {
                if (type == typeof(object))
                {
                    return new ConstantExpression(null);
                }
 
                if (!type.IsValueType || type.IsNullableType())
                {
                    return new TypedConstantExpression(null, type);
                }
            }
            else
            {
                Type valueType = value.GetType();
                if (type == valueType)
                {
                    return new ConstantExpression(value);
                }
 
                if (type.IsAssignableFrom(valueType))
                {
                    return new TypedConstantExpression(value, type);
                }
            }
 
            throw Error.ArgumentTypesMustMatch();
        }
    }
}