What was broken
The C# compiler stores a delegate created from a method group in a static cache field, so it does not have to build it again on every call. ILSpy, the open source .NET decompiler, recognises that pattern and turns it back into readable code. The transform, however, assumed the cache field would be read exactly once.
With _ = (Action<int>)M; the delegate is created and immediately discarded, so the field is never read. The pattern did not match, and the decompiled output kept a field named <>O.<0>__M, a name that cannot be used in C#. That code does not compile (issue #3965).
What we changed
When the cache field has no reads at all, the cache check is replaced by the delegate construction it guarded. The output now contains new Action<int>(M);, which compiles and does the same thing.
How we tested it
We added an Issue3965 test case with nine scenarios: a single discarded conversion, a conversion before and after a use of the same method, several conversions in a row, two to the same method, and conversions inside a condition and a loop. Each has its expected output written out, and the test compares the decompiled result against it.
The result
The change was merged on 19 September 2026. ILSpy also accepted our second change (#4134), which recognises the type test in a Visual Basic exception filter.