How do convert a lambda event subscription to be able to unsubscribe it?

I’m very new to events/delegates so sorry if I use the incorrect terminology.

I’m using an inventory script for Unity, that uses C# events/delegates to subscribe to a right click event on an item slot.

The problem is when I dynamically add new item slots, I need to add the event handlers to the new slots. If I just run UpdateEvents(), the ones that were there in the first place, now has duplicate triggers.

The current code is using a lambda syntax, and I’ve studied these threads on how to create a delegate instance:

Here’s the original lambda subscription:

// This is the lambda expression that I want to unsubscribe to
ItemSlots*.OnRightClickEvent += slot => EventHelper(slot, OnRightClickEvent);*

Here’s what I tried, and I marked with ** on the parts that my IDE highlights as wrong:
// Try 1
EventHandler lambda = slot => EventHelper(slot, OnRightClickEvent);
ItemSlots*.OnRightClickEvent += lambda;*

// Try 2
EventHandler handler = (sender, e) => EventHelper(sender, OnRightClickEvent);
ItemSlots*.OnRightClickEvent += handler;*
// Try 3
var myDelegate = delegate(sender, e) { EventHelper(e, OnRightClickEvent); };
ItemSlots*.OnRightClickEvent += myDelegate;*
I also tried converting it without using lambda, but it doesn’t work like it should. I’m not sure what “slot” refers to in the lambda. Is it the instance triggering the event? Here’s what didn’t work, but didn’t give any errors:
// Try without lambda
ItemSlots*.OnRightClickEvent += OnRightClickEvent;*
Here’s a shortened version of the complete code. I don’t fully understand how the EventHelper()-method works, but it seems to be some shortcut to check for null.
using System;
using System.Collections.Generic;
using UnityEngine;

public abstract class ItemContainer : MonoBehaviour, IItemContainer {
* public List ItemSlots;*

* // There are really 8 event here, but I simplified it*
* public event Action OnRightClickEvent;*

* protected virtual void Awake() {*
* UpdateEvents();*
* SetStartingItems();*
* }*

* public virtual void UpdateEvents() {*
* for (int i = 0; i < ItemSlots.Count; i++) {*
// This is the lambda expression that I want to unsubscribe to
_ ItemSlots*.OnRightClickEvent += slot => EventHelper(slot, OnRightClickEvent);
}
}*_

* private void EventHelper(BaseItemSlot itemSlot, Action action) {*
* if (action != null)*
* action(itemSlot);*
* }*
}

Try this:

 using System;
 using System.Collections.Generic;
 using UnityEngine;
 
 public abstract class ItemContainer : MonoBehaviour, IItemContainer {
     public List<ItemSlot> ItemSlots;
     private List<Action<BaseItemSlot>> listeners = new List<Action<BaseItemSlot>>();
 
     // There are really 8 event here, but I simplified it
     public event Action<BaseItemSlot> OnRightClickEvent;
 
     protected virtual void Awake()
     {
         UpdateEvents();
         SetStartingItems();
     }
 
     public virtual void UpdateEvents()
     {
         for (int i = 0; i < ItemSlots.Count; i++)
         {
             Action<BaseItemSlot> listener = slot => EventHelper(slot, OnRightClickEvent);
             if( listeners.Count <= i )
             {
                listeners.Add(listener);
             }
             else
             {
                 ItemSlots_.OnRightClickEvent -= listeners*;*_

listeners = listener;
}

ItemSlots_.OnRightClickEvent += listeners*;
}
}*_

public virtual void RemoveEvents()
{
for (int i = 0; i < ItemSlots.Count; i++)
ItemSlots_.OnRightClickEvent -= listeners*;
}*_

private void EventHelper(BaseItemSlot itemSlot, Action action)
{
if (action != null)
action(itemSlot);
}
}

I ended up solving it another way, based on some tips I got from other forums, also on naming the events.

public event Action<BaseItemSlot> RightButtonClicked;
public virtual void UpdateEvents() {
	for (int i = 0; i < ItemSlots.Count; i++) {
		// Unsubscribe, subscribe again
		ItemSlots_.RightButtonClicked -= OnRightButtonClicked;	ItemSlots*.RightButtonClicked += OnRightButtonClicked;*_

* }*
* }*
* private void EventHelper(BaseItemSlot itemSlot, Action action) {*
* if (action != null)*
* action(itemSlot);*
* }*
* private void OnRightButtonClicked(BaseItemSlot slot) {*
* EventHelper(slot, RightButtonClicked);*
* }*
It seems there is no issue unsubscribing something that isn’t subscribed, so I always unsubscribe it first. This way I don’t have to keep a list of what’s going on.
Thanks for your help :slight_smile: