public static byte[] HexStringToByteArrayChecked(this string s)
        {
            s.ValidateNotNull(nameof(s));
            foreach (char c in s)
            {
                if (!IsHex(c))
                {
                    ThrowHelpers.ThrowArgumentException("Must provide a hex string.", nameof(s));
                }
            }

            return(s.AsSpan().HexStringToByteArrayUnchecked());

            bool IsHex(char c)
            {
                // at the time of writing, on both x86 and x64, the assembly for this method is 1
                // byte smaller than the assembly for 3 range checks, it has 2 fewer conditional
                // jumps, and the larger 0-9 case is tighter (early return instead of jump to end).
                if ('0' <= c && c <= '9')
                {
                    return(true);
                }

                c = unchecked ((char)(c & 0xFFDF));
                return('A' <= c && c <= 'F');
            }
        }
 protected void ThrowIfDisposed()
 {
     if (this.IsDisposed)
     {
         ThrowHelpers.ThrowObjectDisposedException(this);
     }
 }
        // A version of the above that does slightly less work for IReadOnlyCollection<T> instances.
        // Should JIT to something that gets optimized to something that's only marginally different
        // than the other one, but it's still cheap and easy to do it this way.
        public static void CopyTo <T>(this IReadOnlyCollection <T> collection, T[] array, int arrayIndex = 0)
        {
            collection.ValidateNotNull(nameof(collection));
            array.ValidateNotNull(nameof(array));
            arrayIndex.ValidateInRange(nameof(arrayIndex), 0, array.Length);

            if (array.Length - arrayIndex < collection.Count)
            {
                ThrowHelpers.ThrowArgumentException("Not enough room", nameof(array));
            }

            foreach (T item in collection)
            {
                array[arrayIndex++] = item;
            }
        }
        public static void CopyHexStringToByteArrayUnchecked(this ReadOnlySpan <char> s, Span <byte> b)
        {
            // this isn't really the kind of "check" that "checked / unchecked" was made for... that
            // was more "throw if this string isn't *actually* a hex string".
            if (s.Length != b.Length * 2)
            {
                ThrowHelpers.ThrowArgumentException("Hex string must have 2 chars for every desired output byte.");
            }

            unchecked
            {
                for (int i = 0; i < b.Length; ++i)
                {
                    int hi = s[i * 2] - 65;
                    hi = hi + 10 + ((hi >> 31) & 7);

                    int lo = s[i * 2 + 1] - 65;
                    lo = lo + 10 + ((lo >> 31) & 7) & 0x0f;

                    b[i] = unchecked ((byte)(lo | hi << 4));
                }
            }
        }
        public static void CopyTo <T>(this IEnumerable <T> enumerable, T[] array, int arrayIndex = 0)
        {
            enumerable.ValidateNotNull(nameof(enumerable));
            array.ValidateNotNull(nameof(array));
            arrayIndex.ValidateInRange(nameof(arrayIndex), 0, array.Length);

            bool prevalidate = enumerable.TryGetCount(out var count);

            if (prevalidate && array.Length - arrayIndex < count)
            {
                ThrowHelpers.ThrowArgumentException("Not enough room", nameof(array));
            }

            foreach (T item in enumerable)
            {
                if (!prevalidate && arrayIndex == array.Length)
                {
                    ThrowHelpers.ThrowArgumentException("Not enough room", nameof(array));
                }

                array[arrayIndex++] = item;
            }
        }