I’m working on a custom inspector and I’m trying to populate a GenericMenu with the content of a string array like this:
public override void OnInspectorGUI()
var menu = new GenericMenu();
foreach(string s in typeNames)
menu.AddItem(new GUIContent(s), false, () => Debug.Log("s = " + s));
which works perfectly fine. The menu gets populated with all the different strings.
The problem is that, no matter what option I click on the generic menu later on, the Debug.Log() always prints the first element from the array. Can someone explain to me, why GUIContent(s) works, but the lambda expression doesn’t?
I’m not sure how capturing of variables work in C# lambdas, but I think that’s the problem here…
The state of the string isn’t captured for the lambda, making them all print the same string.
A fix for this is to use the alternative GenericMenu.Menufunction2:
Its signature is
void(object) and the correlated
AddItem-function takes an extra parameter which is the object that should be passed through the expression.
For the case above:
menu.AddItem(new GUIContent(s), false, str => Debug.Log("s = " + (string)str), s);
The only difference between the two is the fact that the parameter
s now will be captured as part of the menu item allowing the item to pass the parameter through the lambda.
My best guess is that the compiler otherwise sees the lambda expression as the same expression for all the added menuitems, and therefore doesn’t need to evaluate the value of
s before the loop is completed (though don’t quote me on that, I’m pretty sure there’s a better explanation of what’s happening behind the scenes here).