Co nie działało
Kompilator C# zapisuje delegat utworzony z grupy metod w statycznym polu pamięci podręcznej, żeby nie tworzyć go od nowa przy każdym wywołaniu. ILSpy, otwarty dekompilator dla .NET, rozpoznaje ten wzorzec i zamienia go z powrotem na czytelny zapis. Transformacja zakładała jednak, że pole z pamięci zostanie odczytane dokładnie raz.
Przy kodzie _ = (Action<int>)M; delegat jest tworzony i od razu odrzucany, więc pole nie jest odczytywane ani razu. Wzorzec nie pasował, a w wyniku dekompilacji zostawało pole o nazwie <>O.<0>__M, której nie da się użyć w C#. Taki kod się nie kompiluje (zgłoszenie #3965).
Co zmieniliśmy
Gdy pole pamięci nie ma żadnego odczytu, sprawdzenie pamięci zostaje zastąpione utworzeniem delegata, które zabezpieczało. W wyniku pojawia się new Action<int>(M);, czyli kod, który się kompiluje i robi to samo.
Jak to sprawdziliśmy
Doszedł zestaw przypadków testowych Issue3965 z dziewięcioma scenariuszami: pojedyncza odrzucona konwersja, konwersja przed użyciem i po użyciu tej samej metody, kilka konwersji pod rząd, dwie do tej samej metody, konwersja w warunku i w pętli. Każdy ma zapisany oczekiwany wynik, z którym test porównuje dekompilację.
Efekt
Zmianę scalono 19 września 2026. W ILSpy przyjęto też drugą naszą zmianę (#4134), która rozpoznaje test typu w filtrze wyjątków z Visual Basica.