Find caller of dynamically added button click's listener

I am adding a list of buttons in code for which I would like to add a click listener.

I am able to add the listener, the issue is I would like to know the button that called the listener.

I have tried the following method, but the passed value to the listener is always the same:

foreach (...)
{
    var button = (Button)GameObject.Instantiate(...);

    packIndex++;

    button.onClick.AddListener(() => this.OnButtonClick(packIndex));
}

public void OnButtonClick(int idx)
{
    // idx is always the latest value in the above loop
}

TL;DR

How do you find the caller from a button click listener?

I’m not sure, but I believe I had a similar problem once and it had to do with the scope in which packIndex exists (it is defined outside of the for loop), and thus each lambda delegate shares the same int (which has been set to the latest value of the loop by the time the delegate is called.

I believe fixing this is as simple as creating a copy of the index inside the foreach loop and use that instead. Like so:

foreach (...)
{
    var button = (Button)GameObject.Instantiate(...);

    packIndex++;
    int copiedIndex = packIndex;

    button.onClick.AddListener(() => this.OnButtonClick(copiedIndex));
}

public void OnButtonClick(int idx)
{
    // do stuffs here
}

I did it like this:

Add the Listener via script, and give it a method which accepts a custom class instance as a parameter. This class will hold the button that is clicked as well as any other data that is neded for the medthod.

public class ButtonClickParameter {
     public Button button;
}

public Button myButton;

void Start() {
      ButtonClickParameter buttonClickParameter = new ButtonClickParameter();
      buttonClickParameter.button = myButton;
	  myButton.onClick.AddListener(delegate { ButtonClick(buttonClickParameter ); });
 }
                
		


private void ButtonClick(ButtonClickParameter bcp) {
     Debug.Log(bcp.button.name);
}