Repository: dotnet/runtime
File: src/libraries/System.Private.CoreLib/src/System/Array.cs (C#)

Code before:
        }

        public static void Copy(Array sourceArray, long sourceIndex, Array destinationArray, long destinationIndex, long length)
        {
            int isourceIndex = (int)sourceIndex;
            int idestinationIndex = (int)destinationIndex;
            int ilength = (int)length;

            if (sourceIndex != isourceIndex)
                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.sourceIndex, ExceptionResource.ArgumentOutOfRange_HugeArrayNotSupported);
            if (destinationIndex != idestinationIndex)
                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.destinationIndex, ExceptionResource.ArgumentOutOfRange_HugeArrayNotSupported);
            if (length != ilength)
                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length, ExceptionResource.ArgumentOutOfRange_HugeArrayNotSupported);

            Copy(sourceArray, isourceIndex, destinationArray, idestinationIndex, ilength);
        }

#if !MONO // implementation details of MethodTable

        // Provides a strong exception guarantee - either it succeeds, or
        // it throws an exception with no side effects.  The arrays must be
        // compatible array types based on the array element type - this
        // method does not support casting, boxing, or primitive widening.
        // It will up-cast, assuming the array types are correct.
        public static unsafe void ConstrainedCopy(Array sourceArray, int sourceIndex, Array destinationArray, int destinationIndex, int length)
        {
            if (sourceArray != null && destinationArray != null)
            {
                MethodTable* pMT = RuntimeHelpers.GetMethodTable(sourceArray);
                if (MethodTable.AreSameType(pMT, RuntimeHelpers.GetMethodTable(destinationArray)) &&
                    pMT->IsSzArray &&
                    length >= 0 && sourceIndex >= 0 && destinationIndex >= 0 &&
                    (uint)(sourceIndex + length) <= sourceArray.NativeLength &&
                    (uint)(destinationIndex + length) <= destinationArray.NativeLength)
                {
                    nuint elementSize = (nuint)pMT->ComponentSize;
                    nuint byteCount = (uint)length * elementSize;
                    ref byte src = ref Unsafe.AddByteOffset(ref Unsafe.As<RawArrayData>(sourceArray).Data, (uint)sourceIndex * elementSize);
                    ref byte dst = ref Unsafe.AddByteOffset(ref Unsafe.As<RawArrayData>(destinationArray).Data, (uint)destinationIndex * elementSize);

                    if (pMT->ContainsGCPointers)
                        Buffer.BulkMoveWithWriteBarrier(ref dst, ref src, byteCount);
                    else
                        SpanHelpers.Memmove(ref dst, ref src, byteCount);

                    // GC.KeepAlive(sourceArray) not required. pMT kept alive via sourceArray
                    return;
                }
            }


Review comment (refactor):
@copilot Could you please create a new private method `void Copy(Array sourceArray, int sourceIndex, Array destinationArray, int destinationIndex, int length, bool reliable)` and use it to deduplicate code between ConstrainedCopy and `void Copy(Array sourceArray, int sourceIndex, Array destinationArray, int destinationIndex, int length)` overloads.

Code after:
        }

        public static void Copy(Array sourceArray, long sourceIndex, Array destinationArray, long destinationIndex, long length)
        {
            int isourceIndex = (int)sourceIndex;
            int idestinationIndex = (int)destinationIndex;
            int ilength = (int)length;

            if (sourceIndex != isourceIndex)
                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.sourceIndex, ExceptionResource.ArgumentOutOfRange_HugeArrayNotSupported);
            if (destinationIndex != idestinationIndex)
                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.destinationIndex, ExceptionResource.ArgumentOutOfRange_HugeArrayNotSupported);
            if (length != ilength)
                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length, ExceptionResource.ArgumentOutOfRange_HugeArrayNotSupported);

            Copy(sourceArray, isourceIndex, destinationArray, idestinationIndex, ilength);
        }

#if !MONO // implementation details of MethodTable

        // Provides a strong exception guarantee - either it succeeds, or
        // it throws an exception with no side effects.  The arrays must be
        // compatible array types based on the array element type - this
        // method does not support casting, boxing, or primitive widening.
        // It will up-cast, assuming the array types are correct.
        public static void ConstrainedCopy(Array sourceArray, int sourceIndex, Array destinationArray, int destinationIndex, int length)
        {
            Copy(sourceArray, sourceIndex, destinationArray, destinationIndex, length, reliable: true);
        }

        // Copies length elements from sourceArray, starting at index 0, to
        // destinationArray, starting at index 0.
        public static unsafe void Copy(Array sourceArray, Array destinationArray, int length)
        {
            if (sourceArray != null && destinationArray != null)
            {
                MethodTable* pMT = RuntimeHelpers.GetMethodTable(sourceArray);
                if (MethodTable.AreSameType(pMT, RuntimeHelpers.GetMethodTable(destinationArray)) &&
                    pMT->IsSzArray &&
                    (uint)length <= sourceArray.NativeLength &&
                    (uint)length <= destinationArray.NativeLength)
                {
                    nuint byteCount = (uint)length * (nuint)pMT->ComponentSize;
                    ref byte src = ref Unsafe.As<RawArrayData>(sourceArray).Data;
                    ref byte dst = ref Unsafe.As<RawArrayData>(destinationArray).Data;

                    if (pMT->ContainsGCPointers)
                        Buffer.BulkMoveWithWriteBarrier(ref dst, ref src, byteCount);
                    else
                        SpanHelpers.Memmove(ref dst, ref src, byteCount);