Main Site Documentation

Array.Copy - what's under the hood


#1

What will happen if I do this? Will it copy each element one by one, or will it copy a chunk of memory from one place to another? In other words, what will be executed - [em]memmove[/em] or [em]for[/em] cycle?

Dim arr1(10), arr2(5) As Byte

Array.Copy(arr2, 0, arr1, 0, 6)

Source code:

if(arraySrc->SameHeader( *arrayDst ))
{
	CLR_UINT8* dataSrc  = arraySrc->GetFirstElement();
	CLR_UINT8* dataDst  = arrayDst->GetFirstElement();
	CLR_UINT8  sizeElem = arraySrc->m_sizeOfElement;

	dataSrc += indexSrc * sizeElem;
	dataDst += indexDst * sizeElem;

	if(!arraySrc->m_fReference)
	{
		memmove( dataDst, dataSrc, length * sizeElem );
	}
	else
	{
		CLR_RT_HeapBlock* ptrSrc = (CLR_RT_HeapBlock*)dataSrc;
		CLR_RT_HeapBlock* ptrDst = (CLR_RT_HeapBlock*)dataDst;
		int               incr;

		if(arraySrc == arrayDst && ptrSrc < ptrDst)
		{
			incr    =       -1;
			ptrSrc += length-1;
			ptrDst += length-1;
		}
		else
		{
			incr = 1;
		}

		for(int i=0; i<length; i++, ptrSrc += incr, ptrDst += incr)
		{
			TINYCLR_CHECK_HRESULT(ptrDst->Reassign( *ptrSrc ));
		}
	}
}
else if(arraySrc->m_fReference && arrayDst->m_fReference)
{
	CLR_RT_TypeDescriptor descSrc;
	CLR_RT_TypeDescriptor descDst;
	CLR_RT_HeapBlock*     ptrSrc   = (CLR_RT_HeapBlock*)arraySrc->GetElement( indexSrc );
	CLR_RT_HeapBlock*     ptrDst   = (CLR_RT_HeapBlock*)arrayDst->GetElement( indexDst );
	
	TINYCLR_CHECK_HRESULT(descDst.InitializeFromObject( *arrayDst )); descDst.GetElementType( descDst );

	for(int i=0; i<length; i++, ptrSrc++, ptrDst++)
	{
		if(ptrSrc->DataType() == DATATYPE_OBJECT && ptrSrc->Dereference() == NULL)
		{
			;
		}
		else
		{
			TINYCLR_CHECK_HRESULT(descSrc.InitializeFromObject( *ptrSrc ));

			if(CLR_RT_ExecutionEngine::IsInstanceOf( descSrc, descDst ) == false)
			{
				TINYCLR_SET_AND_LEAVE(CLR_E_INVALID_CAST);
			}
		}

		TINYCLR_CHECK_HRESULT(ptrDst->Reassign( *ptrSrc ));
	}
}
else
{
	CLR_RT_TypeDescriptor descSrc;
	CLR_RT_TypeDescriptor descDst;
	CLR_RT_HeapBlock      ref;
	CLR_RT_HeapBlock      elem; elem.SetObjectReference( NULL );
	CLR_RT_ProtectFromGC  gc( elem ); 

	TINYCLR_CHECK_HRESULT(descDst.InitializeFromObject( *arrayDst )); descDst.GetElementType( descDst );

	for(int i=0; i<length; i++)
	{
		ref.InitializeArrayReferenceDirect( *arraySrc, indexSrc++ ); TINYCLR_CHECK_HRESULT(elem.LoadFromReference( ref ));

		if(elem.DataType() == DATATYPE_OBJECT && elem.Dereference() == NULL)
		{
			;
		}
		else
		{
			TINYCLR_CHECK_HRESULT(descSrc.InitializeFromObject( elem ));

			if(CLR_RT_ExecutionEngine::IsInstanceOf( descSrc, descDst ) == false)
			{
				TINYCLR_SET_AND_LEAVE(CLR_E_INVALID_CAST);
			}
		}

		ref.InitializeArrayReferenceDirect( *arrayDst, indexDst++ ); TINYCLR_CHECK_HRESULT(elem.StoreToReference( ref, 0 ));
	}
}

#2

@ iamin - I believe it will execute the memmove line.