
How is C# code that uses arrays and assigns elements in arrays implemented in the intermediate language? The stelem instruction is used to store an element inside the memory region pointed to by an array reference. By investigating further, we improve our knowledge of the .NET Framework—this helps us make better decisions about array types.
This .NET IL example shows the stelem instruction. It provides benchmarks of stelem.

When you assign elements in an array, the array itself is pushed onto the stack (newarr). Next the index you are using in the array is pushed onto the stack (ldc), and the value you want to put into the array is pushed onto the stack (ldloc). We demonstrate three C# programs and the IL they are compiled into.
ldc Instruction ldloc InstructionProgram 1 in C#
class Program
{
static void Main()
{
char[] c = new char[100];
c[0] = 'f';
}
}
Program 1 in IL
.method private hidebysig static void Main() cil managed
{
.entrypoint
.maxstack 3
.locals init (
[0] char[] c)
L_0000: ldc.i4.s 100
L_0002: newarr char
L_0007: stloc.0
L_0008: ldloc.0
L_0009: ldc.i4.0
L_000a: ldc.i4.s 0x66
L_000c: stelem.i2
L_000d: ret
}
Program 2 in C#
class Program
{
static void Main()
{
int[] i = new int[100];
i[0] = 5;
}
}
Program 2 in IL
.method private hidebysig static void Main() cil managed
{
.entrypoint
.maxstack 3
.locals init (
[0] int32[] i)
L_0000: ldc.i4.s 100
L_0002: newarr int32
L_0007: stloc.0
L_0008: ldloc.0
L_0009: ldc.i4.0
L_000a: ldc.i4.5
L_000b: stelem.i4
L_000c: ret
}
Program 3 in C#
class Program
{
static void Main()
{
uint[] u = new uint[100];
u[0] = 2;
}
}
Program 3 in IL
.method private hidebysig static void Main() cil managed
{
.entrypoint
.maxstack 3
.locals init (
[0] uint32[] u)
L_0000: ldc.i4.s 100
L_0002: newarr uint32
L_0007: stloc.0
L_0008: ldloc.0
L_0009: ldc.i4.0
L_000a: ldc.i4.s 0x66
L_000c: stelem.i4
L_000d: ret
}
Microsoft states that the stelem opcode in intermediate language "replaces the array element at a given index with the value on the evaluation stack, whose type is specified in the instruction." When you assign an element in an array, the stelem instruction is generated to actually do the work.
OpCodes.Stelem_I2 OpCodes.Stelem_I4 OpCodes.Ldelem_I2 OpCodes.Ldelem_I4
Could certain value type elements be faster than others? I wanted to know if the opcodes perform differently; my research with numeric types, and my previous reading on data types in C, indicated that the unsigned integer data type is most efficient.
Numeric CastsBenchmark of setting array elements char array: 5208 ms int32 array: 4321 ms uint32 array: 4125 ms
Note: 100 million iterations repeated 100 times.

Results. My results show that setting an element in a char array is much slower than an int32 array, and the uint32 array was slighter faster still. This fits with my knowledge from C and lower-level languages. An old optimization trick is to use unsigned integers instead of signed ones.
Uint ExampleWe saw the stelem instructions and discovered that they have performance differences. This gives us insight into our computers' microarchitectures. Diagnosing problems in intermediate language has far greater utility than the benchmarks here: if you have a really difficult problem, then understanding what opcodes like stelem and ldelem do is important.
Intermediate Language