File: src\System\Reflection\MdConstant.cs
Web Access
Project: src\src\coreclr\System.Private.CoreLib\System.Private.CoreLib.csproj (System.Private.CoreLib)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
namespace System.Reflection
{
    internal static class MdConstant
    {
        public static unsafe object? GetValue(MetadataImport scope, int token, RuntimeTypeHandle fieldTypeHandle, bool raw)
        {
            string? stringVal = scope.GetDefaultValue(token, out long buffer, out int length, out CorElementType corElementType);
 
            RuntimeType fieldType = fieldTypeHandle.GetRuntimeType();
 
            if (fieldType.IsEnum && !raw)
            {
                // NOTE: Unlike in `TypeBuilder.SetConstantValue`, if `fieldType` describes
                // a nullable enum type `Nullable<TEnum>`, we do not unpack it to `TEnum` to
                // successfully enter this `if` clause. Default values of `TEnum?`-typed
                // parameters have been reported as values of the underlying type, changing
                // this now might be a breaking change.
 
                long defaultValue = 0;
 
                switch (corElementType)
                {
                    #region Switch
 
                    case CorElementType.ELEMENT_TYPE_VOID:
                        return DBNull.Value;
 
                    case CorElementType.ELEMENT_TYPE_CHAR:
                        defaultValue = *(char*)&buffer;
                        break;
 
                    case CorElementType.ELEMENT_TYPE_I1:
                        defaultValue = *(sbyte*)&buffer;
                        break;
 
                    case CorElementType.ELEMENT_TYPE_U1:
                        defaultValue = *(byte*)&buffer;
                        break;
 
                    case CorElementType.ELEMENT_TYPE_I2:
                        defaultValue = *(short*)&buffer;
                        break;
 
                    case CorElementType.ELEMENT_TYPE_U2:
                        defaultValue = *(ushort*)&buffer;
                        break;
 
                    case CorElementType.ELEMENT_TYPE_I4:
                        defaultValue = *(int*)&buffer;
                        break;
 
                    case CorElementType.ELEMENT_TYPE_U4:
                        defaultValue = *(uint*)&buffer;
                        break;
 
                    case CorElementType.ELEMENT_TYPE_I8:
                        defaultValue = buffer;
                        break;
 
                    case CorElementType.ELEMENT_TYPE_U8:
                        defaultValue = buffer;
                        break;
 
                    case CorElementType.ELEMENT_TYPE_CLASS:
                        return null;
 
                    default:
                        throw new FormatException(SR.Arg_BadLiteralFormat);
                        #endregion
                }
 
                return Enum.ToObject(fieldType, defaultValue);
            }
            else if (fieldType == typeof(DateTime))
            {
                long defaultValue = 0;
 
                switch (corElementType)
                {
                    #region Switch
 
                    case CorElementType.ELEMENT_TYPE_VOID:
                        return DBNull.Value;
 
                    case CorElementType.ELEMENT_TYPE_I8:
                        defaultValue = buffer;
                        break;
 
                    case CorElementType.ELEMENT_TYPE_U8:
                        defaultValue = buffer;
                        break;
 
                    case CorElementType.ELEMENT_TYPE_CLASS:
                        return null;
 
                    default:
                        throw new FormatException(SR.Arg_BadLiteralFormat);
                        #endregion
                }
 
                return new DateTime(defaultValue);
            }
            else
            {
                return corElementType switch
                {
                    CorElementType.ELEMENT_TYPE_VOID => DBNull.Value,
                    CorElementType.ELEMENT_TYPE_CHAR => *(char*)&buffer,
                    CorElementType.ELEMENT_TYPE_I1 => *(sbyte*)&buffer,
                    CorElementType.ELEMENT_TYPE_U1 => *(byte*)&buffer,
                    CorElementType.ELEMENT_TYPE_I2 => *(short*)&buffer,
                    CorElementType.ELEMENT_TYPE_U2 => *(ushort*)&buffer,
                    CorElementType.ELEMENT_TYPE_I4 => *(int*)&buffer,
                    CorElementType.ELEMENT_TYPE_U4 => *(uint*)&buffer,
                    CorElementType.ELEMENT_TYPE_I8 => buffer,
                    CorElementType.ELEMENT_TYPE_U8 => (ulong)buffer,
                    CorElementType.ELEMENT_TYPE_BOOLEAN => (*(int*)&buffer != 0),
                    CorElementType.ELEMENT_TYPE_R4 => *(float*)&buffer,
                    CorElementType.ELEMENT_TYPE_R8 => *(double*)&buffer,
                    CorElementType.ELEMENT_TYPE_STRING => stringVal ?? string.Empty,
                    CorElementType.ELEMENT_TYPE_CLASS => null,
                    _ => throw new FormatException(SR.Arg_BadLiteralFormat),
                };
            }
        }
    }
}