C#C
C#3y ago
Hugh

Using ILGenerator to create and populate a List<string>

I'm currently trying to figure out the ILGenerator procedure to add items to a List.

Using www.sharplab.io I can see that this code:
public class C {
    public List<String> MyStringList { get; set; } = new List<string>{"a", "b"};
}

Generates a constructor that looks like this:
IL_0000: ldarg.0
IL_0001: newobj instance void class [System.Collections]System.Collections.Generic.List`1<string>::.ctor()
IL_0006: dup
IL_0007: ldstr "a"
IL_000c: callvirt instance void class [System.Collections]System.Collections.Generic.List`1<string>::Add(!0)
IL_0011: dup
IL_0012: ldstr "b"
IL_0017: callvirt instance void class [System.Collections]System.Collections.Generic.List`1<string>::Add(!0)
IL_001c: stfld class [System.Collections]System.Collections.Generic.List`1<string> C::'<MyStringList>k__BackingField'
IL_0021: ldarg.0
IL_0022: call instance void [System.Runtime]System.Object::.ctor()
IL_0027: ret


I'm trying to replicate the setting of MyStringList in my own custom constructor, and I'm getting an error saying that it's an invalid program.

Here's my constructor:
Type listType = typeof(List<string>);
ConstructorInfo? listConstructor = listType.GetConstructor(Array.Empty<Type>());
MethodInfo? addMethod = listType.GetMethod("Add");

il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Newobj, listConstructor);
// Start set list members
il.Emit(OpCodes.Dup);
il.Emit(OpCodes.Ldstr, "a");
il.Emit(OpCodes.Callvirt, addMethod); // I think that the issue is with this line and the same one 3 below
il.Emit(OpCodes.Dup);
il.Emit(OpCodes.Ldstr, "b");
il.Emit(OpCodes.Callvirt, addMethod);
// End set list members
il.Emit(OpCodes.Stfld, fieldBuilder);

ConstructorInfo parentConst = parentType.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Array.Empty<Type>(), null) ?? throw new Exception();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Call, parentConst);
il.Emit(OpCodes.Ret);
Was this page helpful?