My code generates a method to dynamically create a multidimensional array assuming an array of dimension lengths, however it seems the the JIT-compiler or even the CLR fails to load items from the dimension lengths array appropriately.
Instead of creating an array of int[10, 10, 10]
, an array of int[10, 10, 0]
is created. It appears to go wrong at OpCodes.Ldelem_I
, however, using OpCodes.Ldelem, typeof(int)
instead just works. The reproduce this behavior, Any CPU settings are required, x86 works fine. This problem occurs on both debug and release mode.
So is this a bug? I feel to uncertain to judge this as I am unable to dig deeper into this.
class Program
{
static void Main(string[] args)
{
CreateMultidimensionalArrayCreator(typeof(int[, ,])).Invoke(new int[] { 10, 10, 10 }); ;
}
static Func<int[], Array> CreateMultidimensionalArrayCreator(Type type)
{
int rank = type.GetArrayRank();
DynamicMethod method = new DynamicMethod(String.Empty, typeof(Array), new Type[] { typeof(int[]) }, typeof(Program), false);
ILGenerator ilGen = method.GetILGenerator();
for (int i = 0; i < rank; i++)
{
// Load element from dimension lengths array
ilGen.Emit(OpCodes.Ldarg_0);
ilGen.Emit(OpCodes.Ldc_I4, i);
ilGen.Emit(OpCodes.Ldelem_I); // Somehow returns 0 for last element, however, OpCodes.Ldelem appears to work fine
// Duplicate element and write to console for diagnostics
ilGen.Emit(OpCodes.Dup);
ilGen.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(int) }));
}
// Get parameters for multidimensional array constructor
//
Type[] parameterTypes = new Type[rank];
for (int i = 0; i < rank; i++)
{
parameterTypes[i] = typeof(int);
}
ilGen.Emit(OpCodes.Newobj, type.GetConstructor(BindingFlags.Public | BindingFlags.Instance, null, parameterTypes, null));
ilGen.Emit(OpCodes.Ret);
return (Func<int[], Array>)method.CreateDelegate(typeof(Func<int[], Array>));
}
}
Replace line:
to line: