InvalidProgramException / Common Language Runtime detected an invalid program
I finally managed to solve this issue.
I unchecked code optimization
in C# Express and that solved the issues. Still the weirdest thing, but since we are using old tools and framework we can not really blame anyone.
Why does this tiny program give Common Language Runtime detected an invalid program?
Based on Sohaiub Jundi's answer, I used SharpLab to dig some more (that site is awesome!), turns out the latest Roslyn build flags this as a compiler error:
error CS8982: A constructor declared in a 'record struct' with parameter list must have a 'this' initializer that calls the primary constructor or an explicitly declared constructor.
So apparently it is a bug in the currently latest .NET 6 version, and will be fixed in an upcoming release.
A workaround for now is to explicitly call the full constructor with all arguments:
using System.Numerics;
var transform = new Transform2(default);
public readonly record struct Transform2(Vector2 Position, float Rotation)
{
public Transform2(Vector2 position) : this(position, default)
{
Position = position;
}
}
Emit IL Like C# Method IL But Get System.InvalidProgramException : Common Language Runtime detected an invalid program
Since you are storing a value in a local variable with stloc.0, you need to declare it:
var il = dm.GetILGenerator();
il.DeclareLocal(typeof(int));
Your second version uses no locals so it does not have this issue.
The first version is what the compiler emits in debug mode, but in release mode it is more like your second example (except for the nop which is unnecessary).
Common Language Runtime detected an invalid program in DateTime getter
You're storing something in slot 0 (with Stloc_0
), but you never declared slot 0.
You need to declare a local first, so ILGenerator
can actually create the slot to store your variable in.
LocalBuilder local = ilGen.DeclareLocal(typeof(DateTimeOffset));
And then:
ilGen.Emit(OpCodes.Stloc, local);
You're using Ldloca_S
to load the address of a local slot, but you never pass the slot to actually load.
ilGen.Emit(OpCodes.Ldloca, local);
(ILGenerator
will turn this into Ldloca_S
if appropriate).
From the docs for ILGenerator.EmitCall
:
Puts a call or callvirt instruction onto the Microsoft intermediate language (MSIL) stream to call a varargs method.
You're not calling a varargs method. Varargs methods are few and far between. You're calling a normal method, so just:
ilGen.Emit(OpCodes.Callvirt, field.GetMethod!);
and:
ilGen.Emit(OpCodes.Call, utcDateTimeMethod!);
Related Topics
Should Idisposable.Dispose() Be Made Safe to Call Multiple Times
Invoking Powershell Cmdlets from C#
Datetime's Representation in Milliseconds
Mocking Static Methods Using Rhino.Mocks
Using Graphics.Drawimage() to Draw Image with Transparency/Alpha Channel
Use a Custom Thousand Separator in C#
What Is the Easiest Way to Do Inter Process Communication in C#
Using Sse in C# Is It Possible
Programmatically Getting the Last Filled Excel Row Using C#
How to Get a Unique Identifier for a Device Within Windows 10 Universal
Using Folderbrowserdialog in Wpf Application
Wpf Controls Needed to Build Chess Application
How to Get a Dimension (Slice) from a Multidimensional Array
The Type Initializer for 'Emgu.Cv.Cvinvoke' Threw an Exception