| File: Microsoft\CSharp\RuntimeBinder\Semantics\ConstVal.cs | Web Access |
| Project: src\runtime\src\libraries\Microsoft.CSharp\src\Microsoft.CSharp.csproj (Microsoft.CSharp) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System; using System.Globalization; namespace Microsoft.CSharp.RuntimeBinder.Semantics { /* * The kind of allocation used in a constant value. * Since CONSTVALs don't store a discriminant for the union * this must be managed by clients. */ internal enum ConstValKind { Int, Double, Long, String, Decimal, IntPtr, Float, Boolean } internal readonly struct ConstVal { // Pre-boxed common values. private static readonly object s_false = false; private static readonly object s_true = true; private static readonly object s_zeroInt32 = 0; private ConstVal(object value) { ObjectVal = value; } public object ObjectVal { get; } public bool BooleanVal => SpecialUnbox<bool>(ObjectVal); public sbyte SByteVal => SpecialUnbox<sbyte>(ObjectVal); public byte ByteVal => SpecialUnbox<byte>(ObjectVal); public short Int16Val => SpecialUnbox<short>(ObjectVal); public ushort UInt16Val => SpecialUnbox<ushort>(ObjectVal); public int Int32Val => SpecialUnbox<int>(ObjectVal); public uint UInt32Val => SpecialUnbox<uint>(ObjectVal); public long Int64Val => SpecialUnbox<long>(ObjectVal); public ulong UInt64Val => SpecialUnbox<ulong>(ObjectVal); public float SingleVal => SpecialUnbox<float>(ObjectVal); public double DoubleVal => SpecialUnbox<double>(ObjectVal); public decimal DecimalVal => SpecialUnbox<decimal>(ObjectVal); public char CharVal => SpecialUnbox<char>(ObjectVal); public string StringVal => SpecialUnbox<string>(ObjectVal); public bool IsNullRef => ObjectVal == null; public bool IsZero(ConstValKind kind) => kind switch { ConstValKind.Decimal => DecimalVal == 0, ConstValKind.String => false, _ => IsDefault(ObjectVal), }; private static T SpecialUnbox<T>(object o) { if (IsDefault(o)) { return default(T); } return (T)Convert.ChangeType(o, typeof(T), CultureInfo.InvariantCulture); } private static bool IsDefault(object o) => o is null || Type.GetTypeCode(o.GetType()) switch { TypeCode.Boolean => default(bool).Equals(o), TypeCode.SByte => default(sbyte).Equals(o), TypeCode.Byte => default(byte).Equals(o), TypeCode.Int16 => default(short).Equals(o), TypeCode.UInt16 => default(ushort).Equals(o), TypeCode.Int32 => default(int).Equals(o), TypeCode.UInt32 => default(uint).Equals(o), TypeCode.Int64 => default(long).Equals(o), TypeCode.UInt64 => default(ulong).Equals(o), TypeCode.Single => default(float).Equals(o), TypeCode.Double => default(double).Equals(o), TypeCode.Decimal => default(decimal).Equals(o), TypeCode.Char => default(char).Equals(o), _ => false, }; public static ConstVal GetDefaultValue(ConstValKind kind) => kind switch { ConstValKind.Int => new ConstVal(s_zeroInt32), ConstValKind.Double => new ConstVal(0.0), ConstValKind.Long => new ConstVal(0L), ConstValKind.Decimal => new ConstVal(0M), ConstValKind.Float => new ConstVal(0F), ConstValKind.Boolean => new ConstVal(s_false), _ => default, }; public static ConstVal Get(bool value) => new ConstVal(value ? s_true : s_false); public static ConstVal Get(int value) => new ConstVal(value == 0 ? s_zeroInt32 : value); public static ConstVal Get(uint value) => new ConstVal(value); public static ConstVal Get(decimal value) => new ConstVal(value); public static ConstVal Get(string value) => new ConstVal(value); public static ConstVal Get(float value) => new ConstVal(value); public static ConstVal Get(double value) => new ConstVal(value); public static ConstVal Get(long value) => new ConstVal(value); public static ConstVal Get(ulong value) => new ConstVal(value); public static ConstVal Get(object p) => new ConstVal(p); } }