private readonly bool TryGetValueSlow()

in sdk/core/Azure.Core.Experimental/src/Variant/Variant.cs [1132:1324]


        private readonly bool TryGetValueSlow<T>(out T value)
        {
            // Single return has a significant performance benefit.

            bool result = false;

            if (_object is null)
            {
                // A null is stored, it can only be assigned to a reference type or nullable.
                value = default!;
                result = Nullable.GetUnderlyingType(typeof(T)) is not null;
            }
            else if (typeof(T).IsEnum && _object is TypeFlag<T> typeFlag)
            {
                value = typeFlag.To(in this);
                result = true;
            }
            else if (_object is T t)
            {
                value = t;
                result = true;
            }
            else if (typeof(T) == typeof(ArraySegment<byte>))
            {
                ulong bits = _union.UInt64;
                if (bits != 0 && _object is byte[] byteArray)
                {
                    ArraySegment<byte> segment = bits != ulong.MaxValue
                        ? new(byteArray, _union.Segment.Offset, _union.Segment.Count)
                        : new(byteArray, 0, 0);
                    value = Unsafe.As<ArraySegment<byte>, T>(ref segment);
                    result = true;
                }
                else
                {
                    value = default!;
                }
            }
            else if (typeof(T) == typeof(ArraySegment<char>))
            {
                ulong bits = _union.UInt64;
                if (bits != 0 && _object is char[] charArray)
                {
                    ArraySegment<char> segment = bits != ulong.MaxValue
                        ? new(charArray, _union.Segment.Offset, _union.Segment.Count)
                        : new(charArray, 0, 0);
                    value = Unsafe.As<ArraySegment<char>, T>(ref segment);
                    result = true;
                }
                else
                {
                    value = default!;
                }
            }
            else if (typeof(T) == typeof(int?) && _object == TypeFlags.Int32)
            {
                int? asInt = (int?)_union.Int32;
                value = Unsafe.As<int?, T>(ref Unsafe.AsRef(in asInt));
                result = true;
            }
            else if (typeof(T) == typeof(long?) && _object == TypeFlags.Int64)
            {
                long? asLong = (long?)_union.Int64;
                value = Unsafe.As<long?, T>(ref Unsafe.AsRef(in asLong));
                result = true;
            }
            else if (typeof(T) == typeof(bool?) && _object == TypeFlags.Boolean)
            {
                bool? asBool = (bool?)_union.Boolean;
                value = Unsafe.As<bool?, T>(ref Unsafe.AsRef(in asBool));
                result = true;
            }
            else if (typeof(T) == typeof(float?) && _object == TypeFlags.Single)
            {
                float? asFloat = (float?)_union.Single;
                value = Unsafe.As<float?, T>(ref Unsafe.AsRef(in asFloat));
                result = true;
            }
            else if (typeof(T) == typeof(double?) && _object == TypeFlags.Double)
            {
                double? asDouble = (double?)_union.Double;
                value = Unsafe.As<double?, T>(ref Unsafe.AsRef(in asDouble));
                result = true;
            }
            else if (typeof(T) == typeof(uint?) && _object == TypeFlags.UInt32)
            {
                uint? asUInt = (uint?)_union.UInt32;
                value = Unsafe.As<uint?, T>(ref Unsafe.AsRef(in asUInt));
                result = true;
            }
            else if (typeof(T) == typeof(ulong?) && _object == TypeFlags.UInt64)
            {
                ulong? asULong = (ulong?)_union.UInt64;
                value = Unsafe.As<ulong?, T>(ref Unsafe.AsRef(in asULong));
                result = true;
            }
            else if (typeof(T) == typeof(char?) && _object == TypeFlags.Char)
            {
                char? asChar = (char?)_union.Char;
                value = Unsafe.As<char?, T>(ref Unsafe.AsRef(in asChar));
                result = true;
            }
            else if (typeof(T) == typeof(short?) && _object == TypeFlags.Int16)
            {
                short? asShort = (short?)_union.Int16;
                value = Unsafe.As<short?, T>(ref Unsafe.AsRef(in asShort));
                result = true;
            }
            else if (typeof(T) == typeof(ushort?) && _object == TypeFlags.UInt16)
            {
                ushort? asUShort = (ushort?)_union.UInt16;
                value = Unsafe.As<ushort?, T>(ref Unsafe.AsRef(in asUShort));
                result = true;
            }
            else if (typeof(T) == typeof(byte?) && _object == TypeFlags.Byte)
            {
                byte? asByte = (byte?)_union.Byte;
                value = Unsafe.As<byte?, T>(ref Unsafe.AsRef(in asByte));
                result = true;
            }
            else if (typeof(T) == typeof(sbyte?) && _object == TypeFlags.SByte)
            {
                sbyte? asSByte = (sbyte?)_union.SByte;
                value = Unsafe.As<sbyte?, T>(ref Unsafe.AsRef(in asSByte));
                result = true;
            }
            else if (typeof(T) == typeof(DateTime?) && _object == TypeFlags.DateTime)
            {
                DateTime? asDateTime = (DateTime?)_union.DateTime;
                value = Unsafe.As<DateTime?, T>(ref Unsafe.AsRef(in asDateTime));
                result = true;
            }
            else if (typeof(T) == typeof(DateTimeOffset?) && _object == TypeFlags.DateTimeOffset)
            {
                DateTimeOffset? asDateTimeOffset = (DateTimeOffset?)new DateTimeOffset(_union.Ticks, TimeSpan.Zero);
                value = Unsafe.As<DateTimeOffset?, T>(ref Unsafe.AsRef(in asDateTimeOffset));
                result = true;
            }
            else if (typeof(T) == typeof(DateTimeOffset?) && _object == TypeFlags.PackedDateTimeOffset)
            {
                DateTimeOffset? asDateTimeOffset = (DateTimeOffset?)_union.PackedDateTimeOffset.Extract();
                value = Unsafe.As<DateTimeOffset?, T>(ref Unsafe.AsRef(in asDateTimeOffset));
                result = true;
            }
            else if (Nullable.GetUnderlyingType(typeof(T)) is Type underlyingType
                && underlyingType.IsEnum
                && _object is TypeFlag underlyingTypeFlag
                && underlyingTypeFlag.Type == underlyingType)
            {
                // Asked for a nullable enum and we've got that type.

                // We've got multiple layouts, depending on the size of the enum backing field. We can't use the
                // nullable itself (e.g. default(T)) as a template as it gets treated specially by the runtime.

                int size = Unsafe.SizeOf<T>();

                switch (size)
                {
                    case (2):
                        NullableTemplate<byte> byteTemplate = new(_union.Byte);
                        value = Unsafe.As<NullableTemplate<byte>, T>(ref Unsafe.AsRef(in byteTemplate));
                        result = true;
                        break;
                    case (4):
                        NullableTemplate<ushort> shortTemplate = new(_union.UInt16);
                        value = Unsafe.As<NullableTemplate<ushort>, T>(ref Unsafe.AsRef(in shortTemplate));
                        result = true;
                        break;
                    case (8):
                        NullableTemplate<uint> intTemplate = new(_union.UInt32);
                        value = Unsafe.As<NullableTemplate<uint>, T>(ref Unsafe.AsRef(in intTemplate));
                        result = true;
                        break;
                    case (16):
                        NullableTemplate<ulong> longTemplate = new(_union.UInt64);
                        value = Unsafe.As<NullableTemplate<ulong>, T>(ref Unsafe.AsRef(in longTemplate));
                        result = true;
                        break;
                    default:
                        ThrowInvalidOperation();
                        value = default!;
                        result = false;
                        break;
                }
            }
            else
            {
                value = default!;
                result = false;
            }

            return result;
        }