Skip to content

Uses of compiler-generated events getting swapped with non-generated events of same type #3575

@nikitalita

Description

@nikitalita

In the below example, there are two events with the same delegate type: a public DlcInstalled that has explicit add/remove and DlcInstalledEvent that does not have an explicit implementation.

There is also an action _dlcInstalledAction which invokes DlcInstalledEvent.

When Ilspy decompiles this, _dlcInstalledAction now invokes DlcInstalled, and it leaves a heap of CompilerGenerated stuff.

Interestingly, If I move the DlcInstalledEvent declaration to the bottom, it decompiles correctly and the input matches the output.

Input:

public static class Steam
{
    public delegate void DlcInstalledEventHandler(uint appId);
    private static event DlcInstalledEventHandler DlcInstalledEvent;
    static Action<uint> _dlcInstalledAction = (appId) =>
    {
        DlcInstalledEvent?.Invoke(appId);
    };
    public static event DlcInstalledEventHandler DlcInstalled
    {
        add
        {
            if(DlcInstalledEvent == null)
            {
                Console.WriteLine("Connecting DlcInstalled signal");
            }
            DlcInstalledEvent += value;
        }
        remove 
        { 
            DlcInstalledEvent -= value; 
            if(DlcInstalledEvent == null)
            {
                Console.WriteLine("Disconnecting DlcInstalled signal");
            }
        }
    }
}

Incorrect output

public static class Steam
{
	public delegate void DlcInstalledEventHandler(uint appId);

	[CompilerGenerated]
	private static DlcInstalledEventHandler m_DlcInstalledEvent;

	private static Action<uint> _dlcInstalledAction = delegate(uint appId)
	{
		Steam.DlcInstalled?.Invoke(appId);
	};

	private static event DlcInstalledEventHandler DlcInstalledEvent
	{
		[CompilerGenerated]
		add
		{
			DlcInstalledEventHandler dlcInstalledEventHandler = Steam.DlcInstalled;
			DlcInstalledEventHandler dlcInstalledEventHandler2;
			do
			{
				dlcInstalledEventHandler2 = dlcInstalledEventHandler;
				DlcInstalledEventHandler value2 = (DlcInstalledEventHandler)Delegate.Combine(dlcInstalledEventHandler2, value);
				dlcInstalledEventHandler = Interlocked.CompareExchange(ref Steam.DlcInstalled, value2, dlcInstalledEventHandler2);
			}
			while ((object)dlcInstalledEventHandler != dlcInstalledEventHandler2);
		}
		[CompilerGenerated]
		remove
		{
			DlcInstalledEventHandler dlcInstalledEventHandler = Steam.DlcInstalled;
			DlcInstalledEventHandler dlcInstalledEventHandler2;
			do
			{
				dlcInstalledEventHandler2 = dlcInstalledEventHandler;
				DlcInstalledEventHandler value2 = (DlcInstalledEventHandler)Delegate.Remove(dlcInstalledEventHandler2, value);
				dlcInstalledEventHandler = Interlocked.CompareExchange(ref Steam.DlcInstalled, value2, dlcInstalledEventHandler2);
			}
			while ((object)dlcInstalledEventHandler != dlcInstalledEventHandler2);
		}
	}

	public static event DlcInstalledEventHandler DlcInstalled
	{
		add
		{
			if (Steam.m_DlcInstalledEvent == null)
			{
				Console.WriteLine("Connecting DlcInstalled signal");
			}
			DlcInstalledEvent += value;
		}
		remove
		{
			DlcInstalledEvent -= value;
			if (Steam.m_DlcInstalledEvent == null)
			{
				Console.WriteLine("Disconnecting DlcInstalled signal");
			}
		}
	}
}

Details

  • Product in use: IlspyCmd
  • Version in use: current master

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions