Skip to content

Explicit delegate constructor not distinguished in C# decompilation. #3921

Description

@PetSerAl

C# allows wrapping method group into delegate constructor. That disable delegate caching and construct new delegate instance on each invocation. That distinction visible in IL but lost in C# decompilation.

Input code

using System;

static class Test
{
	static Action Test1() => M;
	static Action Test2() => new(M);
	static void M() {}
}

Erroneous output

using System;

internal static class Test
{
	private static Action Test1()
	{
		return M;
	}

	private static Action Test2()
	{
		return M;
	}

	private static void M()
	{
	}
}
.class private auto ansi abstract sealed beforefieldinit Test
	extends [System.Runtime]System.Object
{
	// Nested Types
	.class nested private auto ansi abstract sealed beforefieldinit '<>O'
		extends [System.Runtime]System.Object
	{
		.custom instance void [System.Runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
			01 00 00 00
		)
		// Fields
		.field public static class [System.Runtime]System.Action '<0>__M'

	} // end of class <>O


	// Methods
	.method private hidebysig static 
		class [System.Runtime]System.Action Test1 () cil managed 
	{
		// Method begins at RVA 0x2050
		// Header size: 1
		// Code size: 28 (0x1c)
		.maxstack 8

		// sequence point: (line 5, col 27) to (line 5, col 28) in M:\Temp\Test\Test.cs
		IL_0000: ldsfld class [System.Runtime]System.Action Test/'<>O'::'<0>__M'
		IL_0005: dup
		IL_0006: brtrue.s IL_001b

		IL_0008: pop
		IL_0009: ldnull
		IL_000a: ldftn void Test::M()
		IL_0010: newobj instance void [System.Runtime]System.Action::.ctor(object, native int)
		IL_0015: dup
		IL_0016: stsfld class [System.Runtime]System.Action Test/'<>O'::'<0>__M'

		IL_001b: ret
	} // end of method Test::Test1

	.method private hidebysig static 
		class [System.Runtime]System.Action Test2 () cil managed 
	{
		// Method begins at RVA 0x206d
		// Header size: 1
		// Code size: 13 (0xd)
		.maxstack 8

		// sequence point: (line 6, col 27) to (line 6, col 33) in M:\Temp\Test\Test.cs
		IL_0000: ldnull
		IL_0001: ldftn void Test::M()
		IL_0007: newobj instance void [System.Runtime]System.Action::.ctor(object, native int)
		IL_000c: ret
	} // end of method Test::Test2

	.method private hidebysig static 
		void M () cil managed 
	{
		// Method begins at RVA 0x207b
		// Header size: 1
		// Code size: 2 (0x2)
		.maxstack 8

		// sequence point: (line 7, col 18) to (line 7, col 19) in M:\Temp\Test\Test.cs
		IL_0000: nop
		// sequence point: (line 7, col 19) to (line 7, col 20) in M:\Temp\Test\Test.cs
		IL_0001: ret
	} // end of method Test::M

} // end of class Test

Details

  • Product in use: ILSpy
  • ILSpy version: 10.1.1.8388+1377eb6e7351b21112858c8c1df39848f40181ec
  • .NET version: 10.0.10-servicing.26326.116+f7d90799ce4ef09a0bb257852a57248d2a8fb8dd

Metadata

Metadata

Assignees

No one assigned

    Labels

    BugDecompilerThe decompiler engine itself

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions