// IList<U> and IReadOnlyList<U>, where T : U dynamically. See the SZArrayHelper class for details.
public abstract partial class Array : ICloneable, IList, IStructuralComparable, IStructuralEquatable
{
- // Create instance will create an array
- [RequiresDynamicCode("The code for an array of the specified type might not be available.")]
- public static unsafe Array CreateInstance(Type elementType, int length)
- {
- if (elementType is null)
- ThrowHelper.ThrowArgumentNullException(ExceptionArgument.elementType);
- if (length < 0)
- ThrowHelper.ThrowLengthArgumentOutOfRange_ArgumentOutOfRange_NeedNonNegNum();
-
- RuntimeType? t = elementType.UnderlyingSystemType as RuntimeType;
- if (t == null)
- ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_MustBeType, ExceptionArgument.elementType);
- return InternalCreate((void*)t.TypeHandle.Value, 1, &length, null);
- }
-
- public static unsafe Array CreateInstance(Type elementType, int length1, int length2)
- {
- if (elementType is null)
- ThrowHelper.ThrowArgumentNullException(ExceptionArgument.elementType);
- if (length1 < 0)
- ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length1, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
- if (length2 < 0)
- ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length2, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
-
- RuntimeType? t = elementType.UnderlyingSystemType as RuntimeType;
- if (t == null)
- ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_MustBeType, ExceptionArgument.elementType);
- int* pLengths = stackalloc int[2];
- pLengths[0] = length1;
- pLengths[1] = length2;
- return InternalCreate((void*)t.TypeHandle.Value, 2, pLengths, null);
- }
-
- public static unsafe Array CreateInstance(Type elementType, int length1, int length2, int length3)
- {
- if (elementType is null)
- ThrowHelper.ThrowArgumentNullException(ExceptionArgument.elementType);
- if (length1 < 0)
- ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length1, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
- if (length2 < 0)
- ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length2, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
- if (length3 < 0)
- ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length3, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
-
- RuntimeType? t = elementType.UnderlyingSystemType as RuntimeType;
- if (t == null)
- ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_MustBeType, ExceptionArgument.elementType);
- int* pLengths = stackalloc int[3];
- pLengths[0] = length1;
- pLengths[1] = length2;
- pLengths[2] = length3;
- return InternalCreate((void*)t.TypeHandle.Value, 3, pLengths, null);
- }
-
- [RequiresDynamicCode("The code for an array of the specified type might not be available.")]
- public static unsafe Array CreateInstance(Type elementType, params int[] lengths)
- {
- if (elementType is null)
- ThrowHelper.ThrowArgumentNullException(ExceptionArgument.elementType);
- if (lengths == null)
- ThrowHelper.ThrowArgumentNullException(ExceptionArgument.lengths);
- if (lengths.Length == 0)
- ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_NeedAtLeast1Rank);
-
- RuntimeType? t = elementType.UnderlyingSystemType as RuntimeType;
- if (t == null)
- ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_MustBeType, ExceptionArgument.elementType);
-
- // Check to make sure the lengths are all positive. Note that we check this here to give
- // a good exception message if they are not; however we check this again inside the execution
- // engine's low level allocation function after having made a copy of the array to prevent a
- // malicious caller from mutating the array after this check.
- for (int i = 0; i < lengths.Length; i++)
- if (lengths[i] < 0)
- ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.lengths, i, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
-
- fixed (int* pLengths = &lengths[0])
- return InternalCreate((void*)t.TypeHandle.Value, lengths.Length, pLengths, null);
- }
-
- [RequiresDynamicCode("The code for an array of the specified type might not be available.")]
- public static unsafe Array CreateInstance(Type elementType, int[] lengths, int[] lowerBounds)
- {
- if (elementType == null)
- ThrowHelper.ThrowArgumentNullException(ExceptionArgument.elementType);
- if (lengths == null)
- ThrowHelper.ThrowArgumentNullException(ExceptionArgument.lengths);
- if (lowerBounds == null)
- ThrowHelper.ThrowArgumentNullException(ExceptionArgument.lowerBounds);
- if (lengths.Length != lowerBounds!.Length)
- ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RanksAndBounds);
- if (lengths.Length == 0)
- ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_NeedAtLeast1Rank);
-
- RuntimeType? t = elementType.UnderlyingSystemType as RuntimeType;
- if (t == null)
- ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_MustBeType, ExceptionArgument.elementType);
-
- // Check to make sure the lenghts are all positive. Note that we check this here to give
- // a good exception message if they are not; however we check this again inside the execution
- // engine's low level allocation function after having made a copy of the array to prevent a
- // malicious caller from mutating the array after this check.
- for (int i = 0; i < lengths.Length; i++)
- if (lengths[i] < 0)
- ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.lengths, i, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
-
- fixed (int* pLengths = &lengths[0])
- fixed (int* pLowerBounds = &lowerBounds[0])
- return InternalCreate((void*)t.TypeHandle.Value, lengths.Length, pLengths, pLowerBounds);
- }
-
[MethodImpl(MethodImplOptions.InternalCall)]
- private static extern unsafe Array InternalCreate(void* elementType, int rank, int* pLengths, int* pLowerBounds);
+ private static extern unsafe Array InternalCreate(RuntimeType elementType, int rank, int* pLengths, int* pLowerBounds);
// Copies length elements from sourceArray, starting at index 0, to
// destinationArray, starting at index 0.
void ArrayNative::CheckElementType(TypeHandle elementType)
{
// Checks apply recursively for arrays of arrays etc.
- if (elementType.IsArray())
+ while (elementType.IsArray())
{
- CheckElementType(elementType.GetArrayElementTypeHandle());
- return;
+ elementType = elementType.GetArrayElementTypeHandle();
}
// Check for simple types first.
// Check for Void.
if (elementType.GetSignatureCorElementType() == ELEMENT_TYPE_VOID)
COMPlusThrow(kNotSupportedException, W("NotSupported_VoidArray"));
-
- // That's all the dangerous simple types we know, it must be OK.
- return;
}
-
- // ByRefs and generic type variables are never allowed.
- if (elementType.IsByRef() || elementType.IsGenericVariable())
- COMPlusThrow(kNotSupportedException, W("NotSupported_Type"));
-
- // We can create pointers and function pointers, but it requires skip verification permission.
- CorElementType etType = elementType.GetSignatureCorElementType();
- if (etType == ELEMENT_TYPE_PTR || etType == ELEMENT_TYPE_FNPTR)
+ else
{
- return;
+ // ByRefs and generic type variables are never allowed.
+ if (elementType.IsByRef() || elementType.IsGenericVariable())
+ COMPlusThrow(kNotSupportedException, W("NotSupported_Type"));
}
-
- // We shouldn't get here (it means we've encountered a new type of typehandle if we do).
- _ASSERTE(!"Shouldn't get here, unknown type handle type");
- COMPlusThrow(kNotSupportedException);
}
-FCIMPL4(Object*, ArrayNative::CreateInstance, void* elementTypeHandle, INT32 rank, INT32* pLengths, INT32* pLowerBounds)
+FCIMPL4(Object*, ArrayNative::CreateInstance, ReflectClassBaseObject* pElementTypeUNSAFE, INT32 rank, INT32* pLengths, INT32* pLowerBounds)
{
CONTRACTL {
FCALL_CHECK;
} CONTRACTL_END;
OBJECTREF pRet = NULL;
- TypeHandle elementType = TypeHandle::FromPtr(elementTypeHandle);
- _ASSERTE(!elementType.IsNull());
+ REFLECTCLASSBASEREF pElementType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pElementTypeUNSAFE);
// pLengths and pLowerBounds are pinned buffers. No need to protect them.
- HELPER_METHOD_FRAME_BEGIN_RET_0();
+ HELPER_METHOD_FRAME_BEGIN_RET_PROTECT(pElementType);
+ TypeHandle elementType(pElementType->GetType());
+
CheckElementType(elementType);
CorElementType CorType = elementType.GetSignatureCorElementType();
// Find the Array class...
TypeHandle typeHnd = ClassLoader::LoadArrayTypeThrowing(elementType, kind, rank);
+ _ASSERTE(rank < MAX_RANK); // Ensures that the stack buffer size allocations below won't overlow
+
DWORD boundsSize = 0;
INT32* bounds;
- if (pLowerBounds != NULL) {
- if (!ClrSafeInt<DWORD>::multiply(rank, 2, boundsSize))
- COMPlusThrowOM();
- DWORD dwAllocaSize = 0;
- if (!ClrSafeInt<DWORD>::multiply(boundsSize, sizeof(INT32), dwAllocaSize))
- COMPlusThrowOM();
-
- bounds = (INT32*) _alloca(dwAllocaSize);
+ if (pLowerBounds != NULL)
+ {
+ boundsSize = 2 * rank;
+ bounds = (INT32*) _alloca(boundsSize * sizeof(INT32));
for (int i=0;i<rank;i++) {
bounds[2*i] = pLowerBounds[i];
bounds[2*i+1] = pLengths[i];
}
}
- else {
+ else
+ {
boundsSize = rank;
-
- DWORD dwAllocaSize = 0;
- if (!ClrSafeInt<DWORD>::multiply(boundsSize, sizeof(INT32), dwAllocaSize))
- COMPlusThrowOM();
-
- bounds = (INT32*) _alloca(dwAllocaSize);
+ bounds = (INT32*) _alloca(boundsSize * sizeof(INT32));
// We need to create a private copy of pLengths to avoid holes caused
// by caller mutating the array
- for (int i=0;i<rank;i++)
+ for (int i=0; i < rank; i++)
bounds[i] = pLengths[i];
}
static FCDECL2(FC_BOOL_RET, IsSimpleCopy, ArrayBase* pSrc, ArrayBase* pDst);
static FCDECL5(void, CopySlow, ArrayBase* pSrc, INT32 iSrcIndex, ArrayBase* pDst, INT32 iDstIndex, INT32 iLength);
- // This method will create a new array of type type, with zero lower
- // bounds and rank.
- static FCDECL4(Object*, CreateInstance, void* elementTypeHandle, INT32 rank, INT32* pLengths, INT32* pBounds);
+ static FCDECL4(Object*, CreateInstance, ReflectClassBaseObject* pElementTypeUNSAFE, INT32 rank, INT32* pLengths, INT32* pBounds);
// This method will return a TypedReference to the array element
static FCDECL2(Object*, GetValue, ArrayBase* refThisUNSAFE, INT_PTR flattenedIndex);
{
// We just checked above that all lower bounds are zero. In that case, we should actually allocate
// a new SzArray instead.
- RuntimeTypeHandle elementTypeHandle = new RuntimeTypeHandle(typeHandleForArrayType.ToEETypePtr().ArrayElementType);
- int length = lengths[0];
- if (length < 0)
- throw new OverflowException(); // For compat: we need to throw OverflowException(): Array.CreateInstance throws ArgumentOutOfRangeException()
- return Array.CreateInstance(Type.GetTypeFromHandle(elementTypeHandle), length);
+ Type elementType = Type.GetTypeFromHandle(new RuntimeTypeHandle(typeHandleForArrayType.ToEETypePtr().ArrayElementType));
+ return RuntimeImports.RhNewArray(elementType.MakeArrayType().TypeHandle.ToEETypePtr(), lengths[0]);
}
- // Create a local copy of the lenghts that cannot be motified by the caller
- int* pLengths = stackalloc int[lengths.Length];
+ // Create a local copy of the lengths that cannot be modified by the caller
+ int* pImmutableLengths = stackalloc int[lengths.Length];
for (int i = 0; i < lengths.Length; i++)
- pLengths[i] = lengths[i];
+ pImmutableLengths[i] = lengths[i];
- return Array.NewMultiDimArray(typeHandleForArrayType.ToEETypePtr(), pLengths, lengths.Length);
- }
-
- //
- // Helper to create an array from a newobj instruction
- //
- public static unsafe Array NewObjArray(RuntimeTypeHandle typeHandleForArrayType, int[] arguments)
- {
- EETypePtr eeTypePtr = typeHandleForArrayType.ToEETypePtr();
- Debug.Assert(eeTypePtr.IsArray);
-
- fixed (int* pArguments = arguments)
- {
- return ArrayHelpers.NewObjArray((IntPtr)eeTypePtr.ToPointer(), arguments.Length, pArguments);
- }
- }
-
- public static ref byte GetSzArrayElementAddress(Array array, int index)
- {
- if ((uint)index >= (uint)array.Length)
- throw new IndexOutOfRangeException();
-
- ref byte start = ref Unsafe.As<RawArrayData>(array).Data;
- return ref Unsafe.Add(ref start, (IntPtr)(nint)((nuint)index * array.ElementSize));
+ return Array.NewMultiDimArray(typeHandleForArrayType.ToEETypePtr(), pImmutableLengths, lengths.Length);
}
public static IntPtr GetAllocateObjectHelperForType(RuntimeTypeHandle type)
{
// Multidimensional array of rank 1 with 0 lower bounds gets actually allocated
// as an SzArray. SzArray is castable to MdArray rank 1.
- int length = pDimensions[0];
- if (length < 0)
- {
- // Compat: we need to throw OverflowException. Array.CreateInstance would throw ArgumentOutOfRange
- throw new OverflowException();
- }
-
- RuntimeTypeHandle elementTypeHandle = new RuntimeTypeHandle(eeType.ArrayElementType);
- return Array.CreateInstance(Type.GetTypeFromHandle(elementTypeHandle), length);
+ Type elementType = Type.GetTypeFromHandle(new RuntimeTypeHandle(eeType.ArrayElementType));
+ return RuntimeImports.RhNewArray(elementType.MakeArrayType().TypeHandle.ToEETypePtr(), pDimensions[0]);
}
return Array.NewMultiDimArray(eeType, pDimensions, rank);
}
[RequiresDynamicCode("The code for an array of the specified type might not be available.")]
- public static Array CreateInstance(Type elementType, int length)
+ private static unsafe Array InternalCreate(RuntimeType elementType, int rank, int* pLengths, int* pLowerBounds)
{
- if (elementType is null)
- throw new ArgumentNullException(nameof(elementType));
-
- return CreateSzArray(elementType, length);
- }
-
- [UnconditionalSuppressMessage("AotAnalysis", "IL3050:RequiresDynamicCode",
- Justification = "MDArrays of Rank != 1 can be created because they don't implement generic interfaces.")]
- public static unsafe Array CreateInstance(Type elementType, int length1, int length2)
- {
- if (elementType is null)
- throw new ArgumentNullException(nameof(elementType));
- if (length1 < 0)
- throw new ArgumentOutOfRangeException(nameof(length1));
- if (length2 < 0)
- throw new ArgumentOutOfRangeException(nameof(length2));
-
- Type arrayType = GetArrayTypeFromElementType(elementType, true, 2);
- int* pLengths = stackalloc int[2];
- pLengths[0] = length1;
- pLengths[1] = length2;
- return NewMultiDimArray(arrayType.TypeHandle.ToEETypePtr(), pLengths, 2);
- }
+ ValidateElementType(elementType);
- [UnconditionalSuppressMessage("AotAnalysis", "IL3050:RequiresDynamicCode",
- Justification = "MDArrays of Rank != 1 can be created because they don't implement generic interfaces.")]
- public static unsafe Array CreateInstance(Type elementType, int length1, int length2, int length3)
- {
- if (elementType is null)
- throw new ArgumentNullException(nameof(elementType));
- if (length1 < 0)
- throw new ArgumentOutOfRangeException(nameof(length1));
- if (length2 < 0)
- throw new ArgumentOutOfRangeException(nameof(length2));
- if (length3 < 0)
- throw new ArgumentOutOfRangeException(nameof(length3));
-
- Type arrayType = GetArrayTypeFromElementType(elementType, true, 3);
- int* pLengths = stackalloc int[3];
- pLengths[0] = length1;
- pLengths[1] = length2;
- pLengths[2] = length3;
- return NewMultiDimArray(arrayType.TypeHandle.ToEETypePtr(), pLengths, 3);
- }
+ if (pLowerBounds != null)
+ {
+ for (int i = 0; i < rank; i++)
+ {
+ if (pLowerBounds[i] != 0)
+ throw new PlatformNotSupportedException(SR.PlatformNotSupported_NonZeroLowerBound);
+ }
+ }
- [RequiresDynamicCode("The code for an array of the specified type might not be available.")]
- public static Array CreateInstance(Type elementType, params int[] lengths)
- {
- if (elementType is null)
- throw new ArgumentNullException(nameof(elementType));
- if (lengths is null)
- throw new ArgumentNullException(nameof(lengths));
- if (lengths.Length == 0)
- throw new ArgumentException(SR.Arg_NeedAtLeast1Rank);
-
- // Check to make sure the lengths are all positive. Note that we check this here to give
- // a good exception message if they are not; however we check this again inside the execution
- // engine's low level allocation function after having made a copy of the array to prevent a
- // malicious caller from mutating the array after this check.
- for (int i = 0; i < lengths.Length; i++)
- if (lengths[i] < 0)
- ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.lengths, i, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
-
- if (lengths.Length == 1)
+ if (rank == 1)
{
- int length = lengths[0];
- return CreateSzArray(elementType, length);
+ return RuntimeImports.RhNewArray(elementType.MakeArrayType().TypeHandle.ToEETypePtr(), pLengths[0]);
+
}
else
{
- return CreateMultiDimArray(elementType, lengths, null);
- }
- }
+ // Create a local copy of the lenghts that cannot be motified by the caller
+ int* pImmutableLengths = stackalloc int[rank];
+ for (int i = 0; i < rank; i++)
+ pImmutableLengths[i] = pLengths[i];
- [RequiresDynamicCode("The code for an array of the specified type might not be available.")]
- public static Array CreateInstance(Type elementType, int[] lengths, int[] lowerBounds)
- {
- if (elementType is null)
- throw new ArgumentNullException(nameof(elementType));
- if (lengths is null)
- throw new ArgumentNullException(nameof(lengths));
- if (lowerBounds is null)
- throw new ArgumentNullException(nameof(lowerBounds));
- if (lengths.Length != lowerBounds.Length)
- throw new ArgumentException(SR.Arg_RanksAndBounds);
- if (lengths.Length == 0)
- throw new ArgumentException(SR.Arg_NeedAtLeast1Rank);
-
- return CreateMultiDimArray(elementType, lengths, lowerBounds);
- }
-
- [RequiresDynamicCode("The code for an array of the specified type might not be available.")]
- private static Array CreateSzArray(Type elementType, int length)
- {
- // Though our callers already validated length once, this parameter is passed via arrays, so we must check it again
- // in case a malicious caller modified the array after the check.
- if (length < 0)
- throw new ArgumentOutOfRangeException(nameof(length));
-
- Type arrayType = GetArrayTypeFromElementType(elementType, false, 1);
- return RuntimeImports.RhNewArray(arrayType.TypeHandle.ToEETypePtr(), length);
- }
-
- [RequiresDynamicCode("The code for an array of the specified type might not be available.")]
- private static Array CreateMultiDimArray(Type elementType, int[] lengths, int[] lowerBounds)
- {
- Debug.Assert(lengths != null);
- Debug.Assert(lowerBounds == null || lowerBounds.Length == lengths.Length);
-
- for (int i = 0; i < lengths.Length; i++)
- {
- if (lengths[i] < 0)
- throw new ArgumentOutOfRangeException("lengths[" + i + "]", SR.ArgumentOutOfRange_NeedNonNegNum);
+ return NewMultiDimArray(elementType.MakeArrayType(rank).TypeHandle.ToEETypePtr(), pImmutableLengths, rank);
}
-
- int rank = lengths.Length;
- Type arrayType = GetArrayTypeFromElementType(elementType, true, rank);
- return RuntimeAugments.NewMultiDimArray(arrayType.TypeHandle, lengths, lowerBounds);
- }
-
- [RequiresDynamicCode("The code for an array of the specified type might not be available.")]
- private static Type GetArrayTypeFromElementType(Type elementType, bool multiDim, int rank)
- {
- elementType = elementType.UnderlyingSystemType;
- ValidateElementType(elementType);
-
- if (multiDim)
- return elementType.MakeArrayType(rank);
- else
- return elementType.MakeArrayType();
}
private static void ValidateElementType(Type elementType)
{
- if (elementType is not RuntimeType)
- throw new ArgumentException(SR.Arg_MustBeType, nameof(elementType));
while (elementType.IsArray)
{
elementType = elementType.GetElementType()!;
}
[RequiresDynamicCode("The code for an array of the specified type might not be available.")]
+ public static unsafe Array CreateInstance(Type elementType, int length)
+ {
+ if (elementType is null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.elementType);
+ if (length < 0)
+ ThrowHelper.ThrowLengthArgumentOutOfRange_ArgumentOutOfRange_NeedNonNegNum();
+
+ RuntimeType? t = elementType.UnderlyingSystemType as RuntimeType;
+ if (t == null)
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_MustBeType, ExceptionArgument.elementType);
+
+ return InternalCreate(t, 1, &length, null);
+ }
+
+ [UnconditionalSuppressMessage("AotAnalysis", "IL3050:RequiresDynamicCode",
+ Justification = "MDArrays of Rank != 1 can be created because they don't implement generic interfaces.")]
+ public static unsafe Array CreateInstance(Type elementType, int length1, int length2)
+ {
+ if (elementType is null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.elementType);
+ if (length1 < 0)
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length1, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
+ if (length2 < 0)
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length2, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
+
+ RuntimeType? t = elementType.UnderlyingSystemType as RuntimeType;
+ if (t == null)
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_MustBeType, ExceptionArgument.elementType);
+
+ int* pLengths = stackalloc int[] { length1, length2 };
+ return InternalCreate(t, 2, pLengths, null);
+ }
+
+ [UnconditionalSuppressMessage("AotAnalysis", "IL3050:RequiresDynamicCode",
+ Justification = "MDArrays of Rank != 1 can be created because they don't implement generic interfaces.")]
+ public static unsafe Array CreateInstance(Type elementType, int length1, int length2, int length3)
+ {
+ if (elementType is null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.elementType);
+ if (length1 < 0)
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length1, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
+ if (length2 < 0)
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length2, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
+ if (length3 < 0)
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length3, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
+
+ RuntimeType? t = elementType.UnderlyingSystemType as RuntimeType;
+ if (t == null)
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_MustBeType, ExceptionArgument.elementType);
+
+ int* pLengths = stackalloc int[3] { length1, length2, length3 };
+ return InternalCreate(t, 3, pLengths, null);
+ }
+
+ [RequiresDynamicCode("The code for an array of the specified type might not be available.")]
+ public static unsafe Array CreateInstance(Type elementType, params int[] lengths)
+ {
+ if (elementType is null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.elementType);
+ if (lengths == null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.lengths);
+ if (lengths.Length == 0)
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_NeedAtLeast1Rank);
+
+ RuntimeType? t = elementType.UnderlyingSystemType as RuntimeType;
+ if (t == null)
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_MustBeType, ExceptionArgument.elementType);
+
+ // Check to make sure the lengths are all non-negative. Note that we check this here to give
+ // a good exception message if they are not; however we check this again inside the execution
+ // engine's low level allocation function after having made a copy of the array to prevent a
+ // malicious caller from mutating the array after this check.
+ for (int i = 0; i < lengths.Length; i++)
+ if (lengths[i] < 0)
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.lengths, i, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
+
+ fixed (int* pLengths = &lengths[0])
+ return InternalCreate(t, lengths.Length, pLengths, null);
+ }
+
+ [RequiresDynamicCode("The code for an array of the specified type might not be available.")]
+ public static unsafe Array CreateInstance(Type elementType, int[] lengths, int[] lowerBounds)
+ {
+ if (elementType == null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.elementType);
+ if (lengths == null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.lengths);
+ if (lowerBounds == null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.lowerBounds);
+ if (lengths.Length != lowerBounds.Length)
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RanksAndBounds);
+ if (lengths.Length == 0)
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_NeedAtLeast1Rank);
+
+ RuntimeType? t = elementType.UnderlyingSystemType as RuntimeType;
+ if (t == null)
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_MustBeType, ExceptionArgument.elementType);
+
+ // Check to make sure the lengths are all non-negative. Note that we check this here to give
+ // a good exception message if they are not; however we check this again inside the execution
+ // engine's low level allocation function after having made a copy of the array to prevent a
+ // malicious caller from mutating the array after this check.
+ for (int i = 0; i < lengths.Length; i++)
+ if (lengths[i] < 0)
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.lengths, i, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
+
+ fixed (int* pLengths = &lengths[0])
+ fixed (int* pLowerBounds = &lowerBounds[0])
+ return InternalCreate(t, lengths.Length, pLengths, pLowerBounds);
+ }
+
+ [RequiresDynamicCode("The code for an array of the specified type might not be available.")]
public static Array CreateInstance(Type elementType, params long[] lengths)
{
if (lengths == null)
return false;
}
- [RequiresDynamicCode("The code for an array of the specified type might not be available.")]
- public static unsafe Array CreateInstance(Type elementType, int length)
+ private static unsafe Array InternalCreate(RuntimeType elementType, int rank, int* lengths, int* lowerBounds)
{
- if (elementType is null)
- ThrowHelper.ThrowArgumentNullException(ExceptionArgument.elementType);
- if (length < 0)
- ThrowHelper.ThrowLengthArgumentOutOfRange_ArgumentOutOfRange_NeedNonNegNum();
-
- RuntimeType? runtimeType = elementType.UnderlyingSystemType as RuntimeType;
- if (runtimeType == null)
- ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_MustBeType, ExceptionArgument.elementType);
-
- Array? array = null;
- InternalCreate(ref array, runtimeType._impl.Value, 1, &length, null);
- GC.KeepAlive(runtimeType);
- return array;
- }
-
- public static unsafe Array CreateInstance(Type elementType, int length1, int length2)
- {
- if (elementType is null)
- ThrowHelper.ThrowArgumentNullException(ExceptionArgument.elementType);
- if (length1 < 0)
- ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length1, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
- if (length2 < 0)
- ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length2, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
-
- RuntimeType? runtimeType = elementType.UnderlyingSystemType as RuntimeType;
- if (runtimeType == null)
- ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_MustBeType, ExceptionArgument.elementType);
-
- int* lengths = stackalloc int[] { length1, length2 };
- Array? array = null;
- InternalCreate(ref array, runtimeType._impl.Value, 2, lengths, null);
- GC.KeepAlive(runtimeType);
- return array;
- }
-
- public static unsafe Array CreateInstance(Type elementType, int length1, int length2, int length3)
- {
- if (elementType is null)
- ThrowHelper.ThrowArgumentNullException(ExceptionArgument.elementType);
- if (length1 < 0)
- ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length1, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
- if (length2 < 0)
- ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length2, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
- if (length3 < 0)
- ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length3, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
-
- RuntimeType? runtimeType = elementType.UnderlyingSystemType as RuntimeType;
- if (runtimeType == null)
- ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_MustBeType, ExceptionArgument.elementType);
-
- int* lengths = stackalloc int[] { length1, length2, length3 };
- Array? array = null;
- InternalCreate(ref array, runtimeType._impl.Value, 3, lengths, null);
- GC.KeepAlive(runtimeType);
- return array;
- }
-
- [RequiresDynamicCode("The code for an array of the specified type might not be available.")]
- public static unsafe Array CreateInstance(Type elementType, params int[] lengths)
- {
- if (elementType is null)
- ThrowHelper.ThrowArgumentNullException(ExceptionArgument.elementType);
- if (lengths == null)
- ThrowHelper.ThrowArgumentNullException(ExceptionArgument.lengths);
- if (lengths.Length == 0)
- ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_NeedAtLeast1Rank);
-
- RuntimeType? runtimeType = elementType.UnderlyingSystemType as RuntimeType;
- if (runtimeType == null)
- ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_MustBeType, ExceptionArgument.elementType);
-
- for (int i = 0; i < lengths.Length; i++)
- if (lengths[i] < 0)
- ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.lengths, i, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
-
- Array? array = null;
- fixed (int* pLengths = &lengths[0])
- InternalCreate(ref array, runtimeType._impl.Value, lengths.Length, pLengths, null);
- GC.KeepAlive(runtimeType);
- return array;
- }
-
- [RequiresDynamicCode("The code for an array of the specified type might not be available.")]
- public static unsafe Array CreateInstance(Type elementType, int[] lengths, int[] lowerBounds)
- {
- if (elementType == null)
- ThrowHelper.ThrowArgumentNullException(ExceptionArgument.elementType);
- if (lengths == null)
- ThrowHelper.ThrowArgumentNullException(ExceptionArgument.lengths);
- if (lowerBounds == null)
- ThrowHelper.ThrowArgumentNullException(ExceptionArgument.lowerBounds);
- if (lengths.Length != lowerBounds!.Length)
- ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RanksAndBounds);
- if (lengths.Length == 0)
- ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_NeedAtLeast1Rank);
-
- for (int i = 0; i < lengths.Length; i++)
- if (lengths[i] < 0)
- ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.lengths, i, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
-
- RuntimeType? runtimeType = elementType.UnderlyingSystemType as RuntimeType;
- if (runtimeType == null)
- ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_MustBeType, ExceptionArgument.elementType);
-
Array? array = null;
- fixed (int* pLengths = &lengths[0])
- fixed (int* pLowerBounds = &lowerBounds[0])
- InternalCreate(ref array, runtimeType._impl.Value, lengths.Length, pLengths, pLowerBounds);
- GC.KeepAlive(runtimeType);
- return array;
+ InternalCreate(ref array, elementType._impl.Value, rank, lengths, lowerBounds);
+ GC.KeepAlive(elementType);
+ return array!;
}
[MethodImpl(MethodImplOptions.InternalCall)]
- private static extern unsafe void InternalCreate([NotNull] ref Array? result, IntPtr elementType, int rank, int* lengths, int* lowerBounds);
+ private static extern unsafe void InternalCreate(ref Array? result, IntPtr elementType, int rank, int* lengths, int* lowerBounds);
private unsafe nint GetFlattenedIndex(ReadOnlySpan<int> indices)
{