Short Answer: No they produce different IL. You can see this yourself on Try Roslyn.
Array.CreateInstance
The CreateInstance
method is a factory method in the Array
class and it returns a type of Array
. Here is the source code for the method:
[System.Security.SecuritySafeCritical] // auto-generated
public unsafe static Array CreateInstance(Type elementType, int length)
{
if ((object)elementType == null)
throw new ArgumentNullException("elementType");
if (length < 0)
throw new ArgumentOutOfRangeException("length", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
Contract.Ensures(Contract.Result<Array>() != null);
Contract.Ensures(Contract.Result<Array>().Length == length);
Contract.Ensures(Contract.Result<Array>().Rank == 1);
Contract.EndContractBlock();
RuntimeType t = elementType.UnderlyingSystemType as RuntimeType;
if (t == null)
throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"), "elementType");
return InternalCreate((void*)t.TypeHandle.Value, 1, &length, null);
}
Please note the last line of code in the above method. The body of that method is just a semi-colon and it is a method implemented externally elsewhere. Here is the body:
[System.Security.SecurityCritical] // auto-generated
[ResourceExposure(ResourceScope.None)]
[MethodImplAttribute(MethodImplOptions.InternalCall)]
private unsafe static extern Array InternalCreate(void* elementType, int rank, int* pLengths, int* pLowerBounds);
Where is that implemented? It is implemented in arraynative.cpp class. Here is the code:
FCIMPL4(Object*, ArrayNative::CreateInstance, void* elementTypeHandle, INT32 rank, INT32* pLengths, INT32* pLowerBounds) {
{
CONTRACTL {
FCALL_CHECK;
PRECONDITION(rank > 0);
PRECONDITION(CheckPointer(pLengths));
PRECONDITION(CheckPointer(pLowerBounds, NULL_OK));
}
CONTRACTL_END;
OBJECTREF pRet = NULL;
TypeHandle elementType = TypeHandle::FromPtr(elementTypeHandle);
_ASSERTE(!elementType.IsNull());
// pLengths and pLowerBounds are pinned buffers. No need to protect them.
HELPER_METHOD_FRAME_BEGIN_RET_0();
CheckElementType(elementType);
CorElementType CorType = elementType.GetSignatureCorElementType();
CorElementType kind = ELEMENT_TYPE_ARRAY;
// Is it ELEMENT_TYPE_SZARRAY array?
if (rank == 1 && (pLowerBounds == NULL || pLowerBounds[0] == 0)
# ifdef FEATURE_64BIT_ALIGNMENT
// On platforms where 64-bit types require 64-bit alignment and don't obtain it naturally force us
// through the slow path where this will be handled.
&& (CorType != ELEMENT_TYPE_I8)
&& (CorType != ELEMENT_TYPE_U8)
&& (CorType != ELEMENT_TYPE_R8)
#endif
)
{
// Shortcut for common cases
if (CorTypeInfo::IsPrimitiveType(CorType))
{
pRet = AllocatePrimitiveArray(CorType, pLengths[0]);
goto Done;
}
else
if (CorTypeInfo::IsObjRef(CorType))
{
pRet = AllocateObjectArray(pLengths[0], elementType);
goto Done;
}
kind = ELEMENT_TYPE_SZARRAY;
pLowerBounds = NULL;
}
{
// Find the Array class...
TypeHandle typeHnd = ClassLoader::LoadArrayTypeThrowing(elementType, kind, rank);
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);
for (int i = 0; i < rank; i++)
{
bounds[2 * i] = pLowerBounds[i];
bounds[2 * i + 1] = pLengths[i];
}
}
else
{
boundsSize = rank;
DWORD dwAllocaSize = 0;
if (!ClrSafeInt < DWORD >::multiply(boundsSize, sizeof(INT32), dwAllocaSize))
COMPlusThrowOM();
bounds = (INT32*)_alloca(dwAllocaSize);
// 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++)
bounds[i] = pLengths[i];
}
pRet = AllocateArrayEx(typeHnd, bounds, boundsSize);
}
Done:;
HELPER_METHOD_FRAME_END();
return OBJECTREFToObject(pRet);
}
As you can see Array.CreateInstance
uses an external DLL implemented elsewhere, outside of managed code.
new int[4];
This is native to C# so the C# compiler will take care of it and create the array. How? I am not sure.
I hope that clarifies things a little.