Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -27,33 +27,18 @@ public static T[] GetSubArray<T>(T[] array, Range range)

(int offset, int length) = range.GetOffsetAndLength(array.Length);

T[] dest;

if (typeof(T).IsValueType || typeof(T[]) == array.GetType())
if (length == 0)
{
// We know the type of the array to be exactly T[] or an array variance
// compatible value type substitution like int[] <-> uint[].

if (length == 0)
{
return Array.Empty<T>();
}

dest = new T[length];
return Array.Empty<T>();
}
else
{
// The array is actually a U[] where U:T. We'll make sure to create
// an array of the exact same backing type. The cast to T[] will
// never fail.

dest = Unsafe.As<T[]>(Array.CreateInstance(array.GetType().GetElementType()!, length));
}
T[] dest = new T[length];

// In either case, the newly-allocated array is the exact same type as the
// original incoming array. It's safe for us to Buffer.Memmove the contents
// from the source array to the destination array, otherwise the contents
// wouldn't have been valid for the source array in the first place.
// Due to array variance, it's possible that the incoming array is
// actually of type U[], where U:T; or that an int[] <-> uint[] or
// similar cast has occurred. In any case, since it's always legal
// to reinterpret U as T in this scenario (but not necessarily the
// other way around), we can use Buffer.Memmove here.

Buffer.Memmove(
ref MemoryMarshal.GetArrayDataReference(dest),
Expand Down