Originally posted by **Gatongone** March 10, 2024
# Background
When I tried to append a `stfld` to a method body from a TypeDefinition with generic arguments, it got a different instruction with the expected code. Is there any wrong?
See following
```
stfld !0 Foo`1::list
```
and
```
stfld !0 class Foo`1::list
```
# Sample
```CSharp
using Mono.Cecil;
using Mono.Cecil.Cil;
public class SnippetRunner
{
public static void Run(string path)
{
var mp = new ModuleParameters
{
Architecture = TargetArchitecture.AMD64,
Kind = ModuleKind.Dll,
};
using (var assembly = AssemblyDefinition.CreateAssembly(new AssemblyNameDefinition("Foo", Version.Parse("1.0.0.0")), Path.GetFileName(path), mp))
{
//Class : Foo
var cls_Foo_0 = new TypeDefinition("", "Foo`1", TypeAttributes.AnsiClass | TypeAttributes.BeforeFieldInit | TypeAttributes.NotPublic, assembly.MainModule.TypeSystem.Object);
assembly.MainModule.Types.Add(cls_Foo_0);
var gp_T_1 = new Mono.Cecil.GenericParameter("T", cls_Foo_0);
cls_Foo_0.GenericParameters.Add(gp_T_1);
//Field: list
var fld_list_2 = new FieldDefinition("list", FieldAttributes.Private, gp_T_1);
cls_Foo_0.Fields.Add(fld_list_2);
//Method : Bar
var md_Bar_3 = new MethodDefinition("Bar", MethodAttributes.Private | MethodAttributes.HideBySig, assembly.MainModule.TypeSystem.Void);
cls_Foo_0.Methods.Add(md_Bar_3);
md_Bar_3.Body.InitLocals = true;
var il_Bar_4 = md_Bar_3.Body.GetILProcessor();
//Parameters of 'void Bar(T a) => list = a;'
var p_a_5 = new ParameterDefinition("a", ParameterAttributes.None, gp_T_1);
md_Bar_3.Parameters.Add(p_a_5);
il_Bar_4.Emit(OpCodes.Ldarg_0);
il_Bar_4.Emit(OpCodes.Ldarg_1);
il_Bar_4.Emit(OpCodes.Stfld, fld_list_2);
il_Bar_4.Emit(OpCodes.Ret);
//** Constructor: Foo() **
var ctor_Foo_6 = new MethodDefinition(".ctor", MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.RTSpecialName | MethodAttributes.SpecialName, assembly.MainModule.TypeSystem.Void);
cls_Foo_0.Methods.Add(ctor_Foo_6);
var il_ctor_Foo_7 = ctor_Foo_6.Body.GetILProcessor();
il_ctor_Foo_7.Emit(OpCodes.Ldarg_0);
il_ctor_Foo_7.Emit(OpCodes.Call, assembly.MainModule.ImportReference(TypeHelpers.DefaultCtorFor(cls_Foo_0.BaseType)));
il_ctor_Foo_7.Emit(OpCodes.Ret);
assembly.Write(path);
}
}
}
public class TypeHelpers
{
public static MethodReference DefaultCtorFor(TypeReference type)
{
var resolved = type.Resolve();
if (resolved == null)
return null;
var ctor = resolved.Methods.SingleOrDefault(m => m.IsConstructor && m.Parameters.Count == 0 && !m.IsStatic);
if (ctor == null)
return DefaultCtorFor(resolved.BaseType);
return new MethodReference(".ctor", type.Module.TypeSystem.Void, type) {HasThis = true};
}
}
```
Output:
```
.class private auto ansi beforefieldinit Foo`1 extends [mscorlib]System.Object
{
// Fields
.field private !T list
// Methods
.method private hidebysig instance void Bar (!T a) cil managed
{
// Method begins at RVA 0x2050
// Header size: 12
// Code size: 8 (0x8)
.maxstack 2
IL_0000: ldarg.0
IL_0001: ldarg.1
IL_0002: stfld !0 Foo`1::list
IL_0007: ret
} // end of method Foo`1::Bar
.method public hidebysig specialname rtspecialname instance void .ctor () cil managed {...}
} // end of class Foo`1
```
Expected:
```
.class private auto ansi beforefieldinit Foo`1 extends [mscorlib]System.Object
{
// Fields
.field private !T list
// Methods
.method private hidebysig instance void Bar (!T a) cil managed
{
// Method begins at RVA 0x2050
// Header size: 12
// Code size: 8 (0x8)
.maxstack 2
IL_0000: ldarg.0
IL_0001: ldarg.1
IL_0002: stfld !0 class Foo`1::list
IL_0007: ret
} // end of method Foo`1::Bar
.method public hidebysig specialname rtspecialname instance void .ctor () cil managed {...}
} // end of class Foo`1
```
Discussed in https://github.com/jbevain/cecil/discussions/935