Option 1 - calling CopyMemory :
[DllImport("kernel32.dll", SetLastError = false)] static extern void CopyMemory(IntPtr destination, IntPtr source, UIntPtr length); public static void Copy<T>(IntPtr source, T[] destination, int startIndex, int length) where T : struct { var gch = GCHandle.Alloc(destination, GCHandleType.Pinned); try { var targetPtr = Marshal.UnsafeAddrOfPinnedArrayElement(destination, startIndex); var bytesToCopy = Marshal.SizeOf(typeof(T)) * length; CopyMemory(targetPtr, source, (UIntPtr)bytesToCopy); } finally { gch.Free(); } }
Not portable, but has good performance.
Option 2 - unsafe and pointers:
public static void Copy(IntPtr source, ushort[] destination, int startIndex, int length) { unsafe { var sourcePtr = (ushort*)source; for(int i = startIndex; i < startIndex + length; ++i) { destination[i] = *sourcePtr++; } } }
It is required to enable the unsafe parameter in the project build properties.
Option 3 - reflection (just for fun, not used in production ):
Marshal class internally uses the CopyToManaged(IntPtr, object, int, int) method CopyToManaged(IntPtr, object, int, int) for all Copy(IntPtr, <array>, int, int) overloads Copy(IntPtr, <array>, int, int) (at least in .NET 4.5). Using reflection, we can directly call this method:
private static readonly Action<IntPtr, object, int, int> _copyToManaged = GetCopyToManagedMethod(); private static Action<IntPtr, object, int, int> GetCopyToManagedMethod() { var method = typeof(Marshal).GetMethod("CopyToManaged", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic); return (Action<IntPtr, object, int, int>)method.CreateDelegate( typeof(Action<IntPtr, object, int, int>), null); } public static void Copy<T>(IntPtr source, T[] destination, int startIndex, int length) where T : struct { _copyToManaged(source, destination, startIndex, length); }
Since Marshal internal variables can be changed, this method is unreliable and should not be used, although this implementation is probably the closest to other overloads of the Marshal.Copy() method.