What happened to my plain msil?

I am trying to create the following class:

public class MyType
{
    public string MyMethod() { return "Hi"; }
}

My Emit code is as follows:

var assemblyBuilder = GetAssemblyBuilder("MyAssembly");
var moduleBuilder = assemblyBuilder.DefineDynamicModule("MyModule");
var typeBuilder = moduleBuilder.DefineType("MyType", TypeAttributes.Public);
var methodBuilder = typeBuilder.DefineMethod("MyMethod", MethodAttributes.Public, typeof(string), new Type[] { });
var ilBuilder = methodBuilder.GetILGenerator();
ilBuilder.Emit(OpCodes.Nop);
ilBuilder.Emit(OpCodes.Ldstr, "Hi");
ilBuilder.Emit(OpCodes.Stloc_0);
ilBuilder.Emit(OpCodes.Br_S);
ilBuilder.Emit(OpCodes.Ldloc_0);
ilBuilder.Emit(OpCodes.Ret);
var type = typeBuilder.CreateType();

but when I call MyMethodon the instance MyType, I get InvalidProgramException: Common Language Runtime detected an invalid program.

I tried changing the return type to voidand using only EmitWriteLineand Emit(OpCodes.Ret), which works fine, so it should be the IL that I wrote here.

Did I miss something obvious here? A clear explanation would be helpful as I am just starting out with Emit.

Additional information from the comments :

The “original” IL is taken from the IL generation in the LINQ pad.

+4
source share
2

OpCodes.Br_S, @Kendall, , "Hi", :

ilBuilder.DeclareLocal(typeof(string));
ilBuilder.Emit(OpCodes.Nop);
ilBuilder.Emit(OpCodes.Ldstr, "Hi");
ilBuilder.Emit(OpCodes.Stloc_0);
ilBuilder.Emit(OpCodes.Ldloc_0);
ilBuilder.Emit(OpCodes.Ret);

, , ( , ):

ilBuilder.Emit(OpCodes.Ldstr, "Hi");
ilBuilder.Emit(OpCodes.Ret);

( , , ).

, , , :

Label returnLabel = ilBuilder.DefineLabel();

ilBuilder.DeclareLocal(typeof(string));
ilBuilder.Emit(OpCodes.Nop);
/* Load the string "HI" and put it on the evaluation stack. */
ilBuilder.Emit(OpCodes.Ldstr, "Hi");

/* Store "Hi" in the local variable we declared. */
ilBuilder.Emit(OpCodes.Stloc_0);

/* Jump to the return label, which is, err the next line anyway: */
ilBuilder.Emit(OpCodes.Br_S, returnLabel);

/* Mark "returnLabel" here so we can jump to it: */
ilBuilder.MarkLabel(returnLabel);    

/* Load the contents of our local variable, put it on the evaluation stack: */
ilBuilder.Emit(OpCodes.Ldloc_0);

/* Return "Hi", which is now back on top of the evaluation stack: */
ilBuilder.Emit(OpCodes.Ret);

( ILGenerator.DefineLabel, MarkLabel, Emit, OpCodes.Br_S.

, .

+5
ilBuilder.Emit(OpCodes.Br_S);

? br.s , .

+3

All Articles